Home RSS 2.0 ATOM 1.0  CDF  
 
CodeSegment - Carlos Segura Sanz (blog)
 

Continuando con el trabajo que estaba realizando en Access necesitaba poder acceder a las listas de SharePoint e ir agregando el contenido a una tabla de SQL Server.

Como comentaba en el post anterior, por el momento estaba manteniendo una lista de sitios en una tabla de Access, recorriendo dicha tabla cargaba las listas en el SQL Server. Ahora necesito recabar información de los sub-sitios que se encuentran por debajo, con lo cual necesito recuperar las direcciones de dichos sitios para poder cargar los datos en el SQL Server.

Para ello he usado el Web Services Toolkit del office 2003 (se puede descargar aquí), este kit es un complemento que nos ayudará a crear una clase Proxy para acceder a los servicios web.

En este caso voy a usar el servicio webs.asmx para recuperar las sub-webs he modificado el código generado por Web Services Toolkit, dejando el constructor vacio y pasando el código del constructor a un método llamado Connect que usaré para conectarme al sitio.

'*****************************************************************
'Esta clase fue creada por Web Services Toolkit
' de Microsoft Office 2003
'*****************************************************************
 
Private Const c_SERVICE As String = "Webs"
Private Const c_PORT As String = "WebsSoap"
Private Const c_SERVICE_NAMESPACE As String = "http://schemas.microsoft.com/sharepoint/soap/"
 
Private sc_Webs As SoapClient30
Private WSDL_URL As String
 
Private Sub Class_Initialize()
End Sub
 
Public Sub Connect(url As String)
    Dim str_WSML As String
    str_WSML = ""
 
    Set sc_Webs = New SoapClient30
    
    WSDL_URL = url + "\_vti_bin\webs.asmx?wsdl"
    
    sc_Webs.MSSoapInit2 WSDL_URL, str_WSML, c_SERVICE, c_PORT, c_SERVICE_NAMESPACE
    sc_Webs.ConnectorProperty("ProxyServer") = "<CURRENT_USER>"
    sc_Webs.ConnectorProperty("EnableAutoProxy") = True
End Sub
 
Private Sub Class_Terminate()
    'Intercepción de errores
    On Error GoTo Class_TerminateTrap
 
    Set sc_Webs = Nothing
Exit Sub
Class_TerminateTrap:
    WebsErrorHandler ("Class_Terminate")
End Sub
 
Private Sub WebsErrorHandler(str_Function As String)
    'Error SOAP
    If sc_Webs.FaultCode <> "" Then
        Err.Raise vbObjectError, str_Function, sc_Webs.FaultString
    'Error no SOAP
    Else
        Err.Raise Err.Number, str_Function, Err.Description
    End If
End Sub
 
Public Function wsm_WebUrlFromPageUrl(ByVal str_pageUrl As String) As String
    'Intercepción de errores
    On Error GoTo wsm_WebUrlFromPageUrlTrap
 
    wsm_WebUrlFromPageUrl = sc_Webs.WebUrlFromPageUrl(str_pageUrl)
Exit Function
wsm_WebUrlFromPageUrlTrap:
    WebsErrorHandler "wsm_WebUrlFromPageUrl"
End Function
 
Public Function wsm_GetAllSubWebCollection() As MSXML2.IXMLDOMNodeList
    'Intercepción de errores
    On Error GoTo wsm_GetAllSubWebCollectionTrap
 
    Set wsm_GetAllSubWebCollection = sc_Webs.GetAllSubWebCollection()
Exit Function
wsm_GetAllSubWebCollectionTrap:
    WebsErrorHandler "wsm_GetAllSubWebCollection"
End Function
 
Public Function wsm_GetListTemplates() As MSXML2.IXMLDOMNodeList
    'Intercepción de errores
    On Error GoTo wsm_GetListTemplatesTrap
 
    Set wsm_GetListTemplates = sc_Webs.GetListTemplates()
Exit Function
wsm_GetListTemplatesTrap:
    WebsErrorHandler "wsm_GetListTemplates"
End Function
 
Public Function wsm_GetWeb(ByVal str_webUrl As String) As MSXML2.IXMLDOMNodeList
    'Intercepción de errores
    On Error GoTo wsm_GetWebTrap
 
    Set wsm_GetWeb = sc_Webs.GetWeb(str_webUrl)
Exit Function
wsm_GetWebTrap:
    WebsErrorHandler "wsm_GetWeb"
End Function
 
Public Function wsm_GetWebCollection() As MSXML2.IXMLDOMNodeList
    'Intercepción de errores
    On Error GoTo wsm_GetWebCollectionTrap
 
    Set wsm_GetWebCollection = sc_Webs.GetWebCollection()
Exit Function
wsm_GetWebCollectionTrap:
    WebsErrorHandler "wsm_GetWebCollection"
End Function

Ahora puedo conectarme a un sitio y recuperar la lista de webs de dicho sitio.

Para clarificar un poco la respuesta del servicio he pasado la respuesta a un array de dos dimensiones conteniendo el nombre y la dirección del sitio.

Sub Test()
    Dim websService As New clsws_Webs
    Dim resultNodeList As IXMLDOMNodeList
    
    websService.Connect "HTTP://SRVTEST/SITES/CSEGROLLUP"
    
    Set resultNodeList = websService.wsm_GetWebCollection
    Debug.Print resultNodeList.Item(0).XML
    
    Dim aWebs() As String
    
    ProcesaRespuesta resultNodeList, aWebs
    
    For i = 0 To UBound(aWebs)
        Debug.Print aWebs(i, 0)
        Debug.Print aWebs(i, 1)
    Next i
End Sub
 
Sub ProcesaRespuesta(resultWebCollection As IXMLDOMNodeList, ByRef aWebs() As String)
    Dim i As Integer
    Dim webs As IXMLDOMNode
    Dim web As IXMLDOMNode
    
    Set webs = resultWebCollection.Item(0)
    
    ReDim aWebs(webs.childNodes.length, 1)
    
    For i = 0 To webs.childNodes.length - 1
        Set web = webs.childNodes.Item(i)
        aWebs(i, 0) = web.Attributes.getNamedItem("Title").Text
        aWebs(i, 1) = web.Attributes.getNamedItem("Url").Text
    Next
    
End Sub

Ahora un poquito de recursiviad y voila …

Thursday, December 29, 2005 12:23:13 AM (Hora estándar romance, UTC+01:00)   #    Comments [0]   SharePoint-es  | 

Estos días he necesitado pasar datos de mi servidor SQL a SharePoint y viceversa, después de realizar algunas pruebas y mientras no tenga el SQL 2005 (el cual permite mediante los servicios de transformación de datos DTS atacar servicios web).

Con mi SQL 2000 he tratado de hacer un pequeño truco que en otras ocasiones había dado buen resultado, el truco consiste en vincular las tablas a través de Access e incluir dicho archivo en un DTS para pasar los datos, esto no funciona con las tablas vinculadas a SharePoint.

Finalmente lo que he hecho a sido usar una base de datos de Access y vincular tablas a mi SQL Server y a las listas de SharePoint que necesitaba.

De modo que ahora puedo realizar un pequeño programa en visual Basic para traspasar el contenido de una lista a una tabla de SQL Server y viceversa.

Para automatizar el proceso he creado dos funciones en Access que me permiten ir vinculando y desvinculando las listas a mi antojo de manera que puedo mantener una tabla fija con los sites de sharepoint que me interesan, recorrer dicha tabla e ir vinculando, copiando el contenido y  desvinculando las listas.

Function VinculaLista(sSitio, sLista, sNombreTabla)
    DoCmd.TransferDatabase acLink, "WSS", sSitio, acTable, sLista, sNombreTabla
    RefreshDatabaseWindow
End Function
 
Function DesVinculaLista(sNombreTabla)
    DoCmd.DeleteObject acTable, sNombreTabla
End Function

Wednesday, December 28, 2005 3:40:42 PM (Hora estándar romance, UTC+01:00)   #    Comments [0]   SharePoint-es  | 

Buon Natale e Felice Anno Nuovo 
Shinnen omedeto. Kurisumasu Omedeto 
Pax hominibus bonae voluntatis 
Vrolijk Kerstfeest en een Gelukkig Nieuwjaar! 
Merry Christmas & Happy New Year 
Joyeux Noël et Bonne Année! 
Fröhliche Weihnachten und ein glückliches Neues Jahr!

Feliz navidad para todos y una vez más garcias por leer este blog.

Carlos.

Saturday, December 24, 2005 7:33:24 PM (Hora estándar romance, UTC+01:00)   #    Comments [1]    | 

Estas últimas noches he estado depurando algunos fallos del csegRollUp v3 así que en unos días estará la versión 3.1, también el editor de CAML me ha llevado algunas horas que no tenía, de modo que se quedará un poco parado pero en GotDotNet.

Hoy me he encontrado con un problema curioso cuando trataba de abrir hojas de excel desde una biblioteca de documentos, utilizando el sistema que describí el otro día para tener múltiples plantillas de documentos asociadas en una lista, de modo que al usar una plantilla determinada sharepoint se redirija al sitio donde debe guardarse el documento creado con esa plantilla.

El problema se origina al abrir un documento desde el sitio A y guardarlo en el sitio B, y que dicho sitio B sea el que el usuario a seleccionado previamente. Para ello hay que introducir esta macro en el libro de excel (no ha de importar ya que este error solo ocurre con libros que llevan macros).

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
   Application.DefaultFilePath = Application.ActiveWorkbook.FullNameURLEncoded
End Sub

Ahora si, cuando salvemos el libro automáticamente aparecerá el sitio que habíamos seleccionado previamente.

Wednesday, December 21, 2005 8:17:23 PM (Hora estándar romance, UTC+01:00)   #    Comments [0]   SharePoint-es  | 

Days ago I show my last toy project called CAML Editor, this first sketch was only a test application. Now I have the pleasure to announce that the first version is here to stay ;-).

• New tabbed interface
• Code completion and folding support in text editor
• CAML code generator completely rewritten
• Many Bugs fixed
• New Validation error interface inside of the editor


 You can download it here... CAMLEditor v1.0.zip (246,46 KB)

Sunday, December 18, 2005 9:10:09 AM (Hora estándar romance, UTC+01:00)   #    Comments [5]   CAMLEditor  | 

- Via Remco's blog he descubierto este reghost de Mathew Cossier en gotdotnet.com lo he descargado esta tarde y lo he probado con un servidor de pruebas, la verdad es que no ha podido con uno de los sitios pero otros si... de momento buena pinta.

- Via Chris Johnson he leido este whitepaper que aclara algunas de las cuestiones fundamentales acerca de ASP 2.0 / Net 2.0 con SharePoint.

- Via Shane estos enlaces tratando el tema de las páginas fantasma aquí

- Via Andrew Conell los post-SP2 hotfix

- Via Shane - Graphicalwonder estos tabs para usar mediante CSS

- Via ScottGu esta utilidad que permite introducir comandos en linea para sql server express 2005.

Saturday, December 17, 2005 6:33:44 PM (Hora estándar romance, UTC+01:00)   #    Comments [0]    | 

Thanks to Matthew McDermott and to Melvin Santana for this new xsl to render calendars with csegRollUp.

<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" 
xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:utils="urn:script-items">
<msxsl:script language="C#" implements-prefix="utils">
<![CDATA[     
    public string FormatDate(string sDate)
        {              
            if (sDate.Length > 0)            
            {           
                DateTime d = DateTime.Parse(sDate);           
                return d.ToString("u");
            }        
            else             
                return "(Empty)";     
        }    
]]>
</msxsl:script>
<xsl:output method="html" encoding="utf-8" />
  <xsl:template match="/">
    <SCRIPT>
       var dopt = new DateOptions;
       dopt.chDateSep = "/";
       dopt.chTimeSep = ":";
       dopt.SetTimeFormat(1);
       dopt.SetDateOrder(1);
       dopt.SetDOW(0); 
       dopt.webTZOffsetMin = -60;
       dopt.CalendarPeriod = "week";
       var cal = new Calendar(null, null, dopt);
       var rgIcons = new Array;
       rgIcons[0] = "\u003cIMG border=0 width=16 height=16 title=\u0022\u0022 SRC=\u0022/_layouts/images/blank.gif\u0022\u003e";
       rgIcons[1] = "\u003cIMG alt=\u0022\u0022 border=0 width=16 height=16 SRC=\u0022/_layouts/images/blank.gif\u0022";
       <xsl:for-each select="Rows/Row">
          <xsl:if test=”Begin != ‘’ and End != ‘’”>
          cal.AddFullEvent("<xsl:value-of select="utils:FormatDate(Begin)" />","
			<xsl:value-of select="utils:FormatDate(Begin)" />","
			<xsl:value-of select="_SiteTitle" />","
			<xsl:value-of select="Description"/>","
			<xsl:value-of select="Title"/>","
			<xsl:value-of select="_ItemUrl"/>",
			rgIcons);
          </xsl:if>
       </xsl:for-each>
       cal.BuildUI();
    </SCRIPT>
  </xsl:template>
</xsl:stylesheet>

Thursday, December 15, 2005 12:24:43 AM (Hora estándar romance, UTC+01:00)   #    Comments [4]   csegRollUp  | 

Hoy modificando un site (en el que tenía colocada la vista con las plantillas múltiples) he pensado en añadir un pequeño menú para modificar directamente las plantillas de la biblioteca de documentos en vez de crear un nuevo documento usando la plantilla. Finalmente lo he implementado usando el editor de de HTML e introduciendo un menú contextual en cada elemento para poder modificar cada plantilla.

Como estos días alguien me había comentado que tenia problemas al usar el ctx.HttpRoot, pongo el código de ejemplo aquí sobre como montar el  ContextInfo para los menús.

   1:  <script>
   2:  CTX = new ContextInfo();
   3:  CTX.listBaseType = -1;
   4:  CTX.Sample_Context = "CTX";
   5:  CTX.Sample_Page = "";
   6:  CTX.HttpPath = ""; 
   7:  CTX.imagesPath = "/_layouts/images/";
   8:  CTX.ctxId = 999;
   9:   
  10:  function Custom_AddListMenuItems(m, ctx)
  11:  {
  12:     CAMOpt(m, "Editar Plantilla", "EditarPlantilla()", "");
  13:     CAMSep(m);
  14:     return true;
  15:  }
  16:   
  17:  function EditarPlantilla()
  18:  {
  19:       alert(currentItemID);
  20:  }
  21:  </script>

El Html usado para montar el menú

   1:  <table height="100%" 
   2:         cellspacing="0" 
   3:         class="ms-unselectedtitle" 
   4:         onmouseover="OnItem(this)" 
   5:         CTXName="CTX" 
   6:         ItemId="1" 
   7:         MsoPnlId="data">
   8:      <tr>
   9:          <td width="100%" class="ms-vb">
  10:              TEST
  11:          </td>
  12:          <td>
  13:              <img src="http://srvsp/_layouts/images/blank.gif" 
  14:              width="13" style="visibility: hidden" alt="" />
  15:          </td>
  16:      </tr>
  17:  </table>



Para añadir una segunda fila (como en el ejemplo superior) hay que duplicar la tabla.

En el script currentItemId coniene el ItemId de la tabla, si por el contario como ha sido mi caso queremos pasar datos desde el elemento seleccionado al script, basta con añadir un nuevo atributo a la hora de crear la tabla por ejemplo:

   1:  <table height="100%" 
   2:         cellspacing="0" 
   3:         class="ms-unselectedtitle" 
   4:         onmouseover="OnItem(this)" 
   5:         MisDatos="DATOS DE PRUEBA"
   6:         CTXName="CTX" 
   7:         ItemId="1" 
   8:         MsoPnlId="data">

Y después en el script basta con  usar itemTable.MisDatos

   1:  function EditarPlantilla()
   2:  {
   3:       alert(itemTable.MisDatos);
   4:  }

Monday, December 12, 2005 1:00:05 AM (Hora estándar romance, UTC+01:00)   #    Comments [0]   SharePoint-es  | 

Este pequeño truco de Bob Mixon para ocultar los enlaces de la parte superior. document.getElementById('elemento').style.visibility = 'hidden'; Yo lo he usado introduciendolo dentro mi csegModifyMenu webpart ya que el contenido que va dentro forma parte de un script. Los elementos son :

onettopnavbar1002-0 = Home
onettopnavbar1002-1 = Documents and Lists
onettopnavbar1002-2 = Create
onettopnavbar1002-3 = Site Settings
onettopnavbar1002-4 = Help

Vía Mohamed Zaki's este artículo de Technet sobre la prevención de desastres en SharePoint.

Joel Oleson's actualización del Recicle Bin 1.1 puede descargarse en GotDotNet SharePoint Tools Site.también via Joel, este divisor de bases de datos para windows sharepoint services que puede encontrarse aquí.

Howard van Rooijen's ha publicado su primera versión del Conchango Xml Visualizer for Visual Studio 2005. Más información aquí.

Saturday, December 10, 2005 8:14:48 PM (Hora estándar romance, UTC+01:00)   #    Comments [0]   SharePoint-es  | 

Updated v1.0 is here

My last project has changed of name, I believe that CAML XML EDITOR will be called.

Join to workspaces.gotdotnet.com/CAMLEditor

At the moment he is a simple XML editor that allows simultaneously to publish the code by fragments (use the context menu in editor) that can are validated themselves. Also has a HTML preview to show the HTML code generated.

And a little CAML generator, you can select any CAML then you has the correct XML, if you select a reference in the XML you can expand it using the context menu.

 You can download it here... CAMLEditor.zip (203,29 KB) Version 1.0

Tuesday, December 06, 2005 9:38:10 AM (Hora estándar romance, UTC+01:00)   #    Comments [1]   CAMLEditor | SharePoint  | 

Para la mayoría de los que trabajamos con SharePoint, el personalizar listas, sitios o áreas usando CAML, seré suave, es un INFIERNO, pero para bien o para mal vamos a tener que convivir con el.

No quiero entrar en detalles acerca de lo bueno o malo, de lo dificultoso o no que pueda llegar a ser, por que como ya he dicho antes hay que convivir con el. Así que he pensado en ser más tolerante y tratar de solucionar los problemas en la medida de lo posible.

Por lo general uso un pequeño truco desde hace tiempo (Todd Bleeker lo comento la semana pasada yo pensaba que era algo de dominio publico)  para pulir las listas antes de integrarlas en SharePoint. Básicamente yo edito la lista en SharePoint, personalizo los campos y las vistas (cosas que son incomodas léase INFERNALES en CAML), después guardo la lista como una plantilla, la paso a mi ordenador, renombro la plantilla como .CAB, descomprimo el archivo con lo que obtengo (manifest.xml, x0000000.000) y edito el archivo manifest.xml

El archivo manifest.xml contiene la definición de la lista en nuestro querido CAML, con un editor de XML y con paciencia edito la barra de botones u otras cosas que necesite cambiar.

Una vez realizados los cambios comprimo de nuevo todos los archivos y los subo al portal, para finalmente crear una lista usando la plantilla modificada.

Ayer por la tarde pensé en como podría automatizar un poco el proceso, pensé en escribir un pequeño notepad que automáticamente realizara el proceso de extracción, edición del manifest.xml y compresión.

Durante la primera media hora me dedique a buscar una biblioteca ó componente que me permitiese trabajar con archivos “.cab” desde Windows Forms. No hubo éxito. (Si alguien conoce alguna que por favor me lo indique).

Visto que no podía subsanar el problema pensé en ejecutar el proceso “cabarc.exe”  y listo.

Bien, en unos minutos abría el archivo “.stp”, extraía los archivos y estaba editando el manifest.xml. Y LLEGO LA IDEA.

Editar un archivo .xml sencillo no es un problema, pero cuando se trata de un CAML, es un autentico caos. ¿Cómo podría editar el archivo de manera más amigable?

Dos horas después tenía un pequeño editor de XML, conectado a un TextBox, y ahora se veía un poquito mejor.

Después cambie el editor por un fabuloso ICSharp.Code.TextEditor hummm resalta la sintaxis, después un control para previsualizar nodos del XML en HTML en un navegador y ver el código que se va a generar… y entonces eran las 3 de la mañana.

Una horita más y otra vez gracias al CAML Schema de Carsten Keutmann, podía validar cada sección que iba editando … buff es hora de irse a la cama.

La cosa es que como nadie se decide por el momento a hacer nada, he pensado en crear un workspace en gotdotnet.com (workspaces.gotdotnet.com/SharePointListTemplateEditor)

El código, sucio, sucio, sucio, como generalmente comienzan este tipo de herramientas, pero ya es hora de ir pensando en hacer algo ¿NO? 

Ale unas pantallitas para animar al personal a que se una al proyecto.

 

[Imagen] [Imagen] [Imagen]

Thursday, December 01, 2005 8:31:36 PM (Hora estándar romance, UTC+01:00)   #    Comments [0]   CAMLEditor | SharePoint-es  | 


Copyright © 2008 Carlos Segura. All rights reserved.