jueves, 26 de marzo de 2009

Reparar archivos que producen el mensaje ERROR READING FILE en Sharepoint Designer

Síntomas:
Al guardar una pagina ASPX repetidas veces en Sharepoint Designer 2007, aparece el mensaje "ERROR READING FILE"

La pagina en la que me sucede en mi caso Tiene un DataView web part con un datasource (con 2 listas de sharepoint Vinculadas), la toolbar de sharepoint con filtrado y arroja un buen informe agrupando datos y haciéndolos Expandibles y Colapsables.




Causa:
Por algún motivo que no me explico se van generando espacios y lineas en blanco entre etiquetas, este se va MULTIPLICANDO cada vez que grabamos el fichero.

Solucion NUEVA:
He creado una herramienta que lo repara de un click, podeis verlo aquí
http://sharepointworks.blogspot.com/2009/06/sharepoint-error-reading-file-repair.html

Solucion1:
Si detectas que esta ocurriendo antes de que el archivo alcance 8 Mb, puedes solucionarlo a través del editor del Sharepoint designer

1º Selecciona 2 lineas en Blanco
2º Seleccionar en el menú superior Edit>Replace
3º Pulsa el botón "Replace all"
4º Guardar el archivo.




Solucion2:
Ya sale el mensaje ERROR READING FILE, y no podemos abrir el fichero con el editor de Sharepoint Designer.

1º Botón derecho sobre el archivo, para abrir el menú contextual.
2º Open With > NOTEPAD.
3º Limpiar los espacios en blanco Reemplazando masivamente o a Mano, hasta que el fichero sea mas pequeño de 8 Mb.
4º Guardar.




Consejo:
Mantener la versión actualizada, ya esta disponible el SP1 de Sharepoint Designer 2007 en el que se corrigen muchos errores. La puedes obtener pulsando aquí

miércoles, 25 de marzo de 2009

Vínculos con parámetros en Sharepoint Designer (XSLT)

Objetivo:
Explicar de forma sencilla como crear vínculos o botones que se generen con parámetros en Sharepoint Designer, usando XSLT
Para posteriormente recogerlo el la pagina vinculada.

Ingredientes:
Un vínculo Anchor o un Botón
Una variable XSL de un datasource o un Parámetro (Parameter Binding)

Receta:
Esta es la forma facil de hacer un vinculo con parametro en sharepoint designer usando un DataView con el datasource configurado

<a href="EditForm.aspx?ID={@ID}"><img border="0" alt="Edit" src="/_layouts/images/edititem.gif" /></a>

De esta forma lo podemos poner en un botón con la diferencia que obtenemos el valor del parameterbing

<input type="button" value="Insertar nuevo Subindice" name="btnNuevoSubindice">
<xsl:attribute name="onclick">javascript: document.location.href='../Subindices/NewForm.aspx?IDPPTA=<xsl:value-of select="$IDPPTA" /></xsl:attribute>'
</input>


No olvidar poner el parametro en la seccion <parameterbindings> del webpart:
<ParameterBinding Name="IDPPTA" Location="QueryString(ID)" DefaultValue="120"/>

Truco: En este caso lo obtenemos de la queryString y le pongo un valor por defecto para que recupere datos en preview y poder diseñar comdodamente usando el Sharepoint designer.

De esta forma me he creado un autonumerador de elementos teniendo en cuenta que el datasource esta filtrado por parametro

<input type="button" value="Insertar nuevo Subindice" name="btnInsertarNuevo2">
<xsl:attribute name="onclick">javascript: document.location.href='../Subindices/NewForm.aspx?IDPPTA=<xsl:value-of select="dsQueryResponse/Rows/Row[1]/@Propuesta" />&NEWSUBNUM=<xsl:value-of select="ddwrt:Max(/dsQueryResponse/Rows/Row/@Cod_subindice)+1</a>" />'</xsl:attribute> </input>

Obtenemos el mismo efecto usando un vínculo
<a alt="Nuevo"><xsl:attribute name="href">../Subindices/NewForm.aspx?IDPPTA=<xsl:value-of select="dsQueryResponse/Rows/Row[1]/@Propuesta" />&NEWSUBNUM=<xsl:value-of select="ddwrt:Max(/dsQueryResponse/Rows/Row/@Cod_subindice)+1</a>" /></xsl:attribute>Añadir un Nuevo registro autonumerado</a>


Nota: "'" es la comilla ya que en XSLT no se pueden poner directamente
Espero os resulte de utilidad

Otra forma: Se puede hacer en vez de pasar el parametro por GET, se pase por post si creamos un formulario oculto con campos hidden, asi no son visibles los parametros, pero hay que recogerlo del form en vez del la QueryString

http://www.robertomarcos.com/

lunes, 23 de marzo de 2009

Como corromper los vínculos de una lista de sharepoint, facil facil

Esto es un aviso para todos,

Sharepoint designer ya es bastante inestable, pero si probamos a renombrar una pagina ASPX de edición de lista, nuevo o visualización para personalizar la página en cuestión..... puede parecer que ha funcionado, si piensas que renombrando una página y poniendo de nuevo el mismo nombre de archivo va a funcionar, lo llevas claro.

Al realizar esto(Renombrar el archivo), lo que obtenemos, es una lista corrupta, si entramos en la página de propiedades de la lista en la pestaña de Supporting Files, que curiosamente es la que tiene los vínculos para que la TOOLBAR de sharepoint, osea que nos la hemos cargado.... a veces dando a browse se puede arreglar, pero .... muy pocas veces. Un buen infierno rico rico.

Al pulsar en el toolBar >NEW saldra un mensaje de URL ERROR, eso significa que efectivamente la hemos corrompido bien, justo lo que necesitamos.....


Para que esto no nos ocurra os pongo este Procedimiento recomendado para customización

1º Copiar la pagina con Copy and Paste
2º Editar la copia y probar la customizacion guardando
3º Seleccionar todo el CÓDIGO, y copiar
4º Hacer CheckOut del archivo EditForm.aspx, viewForm.aspx o el que sea.
5º Abrir EditForm.aspx,ViewForm.aspx o el que sea
6º Seleccionar todo el CÓDIGO y pegar.
7º Hacer CheckIn (a veces da unos mensajes de error en este paso, que se solucionan poniendo el foco en la FolderList del website y pulsando F5 , no he encontrado explicación al BUG)


Esta es una lista sin corromper los vínculos.

Ajustando valores a controles ListFormField (al cargar) desde la QueryString

Objetivo:
Ajustar valores por defecto en controles obteniendolos desde la QueryString
Receta:
Para ajustar correctamente el valor obteniendolo de la QueryString, hemos de usar javascript.
Hay que tener cuidado al cambiar los ID de los controles desde el sharepoint designer, porque el codigo del DataBind es generado y utiliza funciones con el nombre ff33,ff34,... (ffNUMERO) y se cargará el valor en el control pero al guardar los valores y hacer el commit desde el formActionButton, no se guardan los valores. Por lo que recomiendo usar los nombres que asigna Sharepoint designer si no se entiende bien el codigo.

----

<script type="text/javascript">
// Este Javascript ajusta el valor por defecto de un LookupField// Hay que pegarlo en el NewForm dentro del tag PlaceHolderMain

_spBodyOnLoadFunctionNames.push("fillDefaultValues");

function fillDefaultValues() {

var qs = location.search.substring(1, location.search.length);
var args = qs.split("&"); var vals = new Object();
for (var i=0; i < args.length; i++) {
var nameVal = args[i].split("=");
var temp = unescape(nameVal[1]).split('+');
nameVal[1] = temp.join(' ');
vals[nameVal[0]] = nameVal[1];
}

getTagFromIdentifier("input","idEmpleado").value=vals["IDEMPLEADO"];
// setFieldValueFromFieldName("idEmpleado", vals["IDEMPLEADO"]); Esto funciona bien para los campos Lookup
setFieldValueFromFieldName("IdPuesto", vals["IDNUEVOPUESTO"]);
setLabelValueFromFieldName("lblIdEmpleado", vals["IDEMPLEADO"]);
}

function setFieldValueFromFieldName(fieldName,value){
if (value == undefined) return;
var theSelect = getTagFromIdentifierAndTitle("input","TextField",fieldName); theSelect.value=value;
}
function setLabelValueFromFieldName(fieldName,value){ if (value == undefined) return;
var theSelect = getTagFromIdentifier("span",fieldName);
theSelect.value=value; theSelect.innerText=value; theSelect.Text=value;
}

function setLookupFromFieldName(fieldName, value) {
if (value == undefined) return;
var theSelect = getTagFromIdentifierAndTitle("select","Lookup",fieldName);
// Si el control tiene mas de 20 elementos en la lista se renderiza con ajax por lo que hay que seleccionarlo de otra manera
// ya que se renderiza como input no como select
if (theSelect == null) {
var theInput = getTagFromIdentifierAndTitle("input","",fieldName);
ShowDropdown(theInput.id);
//this function is provided by SharePoint
var opt=document.getElementById(theInput.opt);
setSelectedOption(opt, value); OptLoseFocus(opt);
//this function is provided by SharePoint
} else {
setSelectedOption(theSelect, value);
}
}

function setSelectedOption(select, value) {
var opts = select.options;
var l = opts.length;
if (select == null) return;
for (var i=0; i < l; i++) {
if (opts[i].value == value) {
select.selectedIndex = i;
return true;
}
}
return false;
}
function getTagFromIdentifier(tagName, identifier) {
var len = identifier.length;
var tags = document.getElementsByTagName(tagName);
for (var i=0; i < tags.length; i++) {
var tempString = tags[i].id;
if (identifier == "" tempString.indexOf(identifier) == tempString.length - len) {
return tags[i];
}
}
return null;
}
function getTagFromIdentifierAndTitle(tagName, identifier, title) {
var len = identifier.length;
var tags = document.getElementsByTagName(tagName);
for (var i=0; i < tags.length; i++) {
var tempString = tags[i].id;
if (tags[i].title == title && (identifier == "" tempString.indexOf(identifier) == tempString.length - len)) {
return tags[i];
}
}
return null;
}
function getTagFromTitle(tagName, title) {
var tags = document.getElementsByTagName(tagName);
for (var i=0; i < tags.length; i++) {
if (tags[i].title == title) {
return tags[i];
}
}
return null;
}
function queryString(parameter) {
var loc = location.search.substring(1, location.search.length);
var param_value = false;
var params = loc.split("&");
for (i=0; i<params.length;i++) {
param_name = params[i].substring(0,params[i].indexOf('='));
if (param_name == parameter) {
param_value = params[i].substring(params[i].indexOf('=')+1)
}
}
if (param_value) {
return param_value;
} else {
return false;
//Here determine return if no parameter is found
}
}
</script>

Forma Directa de acceso a QueryString con JSRequest (Nativo en Sharepoint):

<script>
JSRequest.EnsureSetup();
var itemId = JSRequest.QueryString["PageView"];
alert(´Query String - ´ + itemId);
itemId = JSRequest.FileName;
alert(´Current Page - ´ + itemId); itemId = JSRequest.PathName;
alert(´Current Path - ´ + itemId);
</script>


RECOMENDACIÓN:
Si encadenáis listas con lookup usados como clave foránea, os recomiendo renderizar los controles como TEXTBOX en vez de como sharepoint ListFormField ya que seguramente queréis ocultar los campos con ID.De lo contrario veréis como se despliega el combo y a medida que vais teniendo mas datos, se ralentiza la página.

http://www.robertomarcos.com/

Filtrado dinamico de DataSource en Sharepoint Designer

Tras buscar bastante en Internet con el objetivo de filtrar Datasources he encontrado este método que no es muy limpio que digamos pero que funciona, sin practicamente programar nada.

INGREDIENTES:
Vamos a necesitar un datasource y un control texbox (Puede estar oculto con style="display:none"), al cual le vamos a ajustar el valor recogido (por javascript) que queremos poner como filtro en el datasource, ajustándolo para que se filtre con un parámetro (ParameterBinding) el cual obtiene su valor del control textbox.

RESULTADO:
Podemos filtrar dinamicámente usando javascript el datasource.... esto da mucho juego, ya que podemos hacer linked combos, o mejor aun cascading Combos y un largo etc.... bueno cada uno que se las ingenie.
Hay muchos customfields de sharepoint que hacen esto pero no he consegido hacer cosas muy complejas, ya que no funcionan correctamente o peor aún , cuando crees que funciona y quieres cargar datos masivamente, empezamos a encontrarnos con sorpresas.

RECETA:
En el datasource, añadimos un parámetro al cual le ajustamos la propiedad Location para que recoja el valor del asp:TextBox y se filtren los resultados.

<ParameterBinding Name="HttpHost" Location="Control(MyHttpHost, Text)"
DefaultValue="" />

Y añadimos el siguiente código a la página.

<asp:TextBox ID="MyHttpHost" runat="server" Visible="false" /><script runat="server">protected void Page_Load(){ MyHttpHost.Text = SPContext.Current.Site.Url.Replace(SPContext.Current.Site.ServerRelativeUrl, ""); }</script>

Nota: Puedes encontrar mas artículos como este si buscas por "Control()"
Fuente: StackOverFlow


miércoles, 18 de marzo de 2009

Saludos a toda la comunidad

Hola,
Me presento como Roberto Marcos, soy consultor de IT y tras una larga temporada trabajando con sharepoint me he encontrado tantos problemas que he decidido postear muchas soluciones y procedimientos de trabajo que hacen posible desarrollar aplicaciones con sharepoint sin morir pero sufriendo un poco en el intento.
Poco a poco iré rellenando el blog con post que espero resulten de utilidad a la comunidad que trabaja con estas herramientas tan buenas que por desgracia aun están en pañales y provocan tantos sufrimientos.

Saludos a todos.
RobertoMarcos.com