cancel
Showing results for 
Search instead for 
Did you mean: 

AYUDA: Como crear botón para exportar a excel resultados de busqueda, Alfresco Share

magarcia_sm
Star Contributor
Star Contributor
Hola a todos,
   Necesito ayuda con la siguiente cuestión. Quiero añadir un botón a la búsqueda avanzada en Alfresco Share que me exporte los resultados de la búsqueda a excel.
Estoy siguiendo como referencia este tutorial.

https://sudheerreddyduganapalli.wordpress.com/2015/01/21/alfresco-share-export-to-excel-from-yui-dat...

He creado todos los archivos tal como indica, pero estoy algo perdido a la hora de crear el botón que llama a la función "exportToEXCEL".
Imagino que el archivo que tengo que tocar para añadir el botón a la vista de Advanced Search es el siguiente "tomcat\webapps\share\components\search\advsearch.js"
He creado el botón pero no tengo muy claro que pasarle como parámetros.

¿Estoy tocando en el archivo correcto? y si es así ¿estoy haciendo algo mal?

¿Alguna idea de por donde puedo tirar? Toda ayuda es bienvenida!

Gracias!

<javascript>
/**
* Advanced Search component.
*
* @namespace Alfresco
* @class Alfresco.AdvancedSearch
*/
(function()
{
   /**
    * YUI Library aliases
    */
   var Dom = YAHOO.util.Dom,
       Event = YAHOO.util.Event,
       Bubbling = YAHOO.Bubbling;

   /**
    * Alfresco Slingshot aliases
    */
   var $html = Alfresco.util.encodeHTML;

   /**
    * Advanced Search constructor.
    *
    * @param {String} htmlId The HTML id of the parent element
    * @return {Alfresco.AdvancedSearch} The new AdvancedSearch instance
    * @constructor
    */
   Alfresco.AdvancedSearch = function(htmlId)
   {
      Alfresco.AdvancedSearch.superclass.constructor.call(this, "Alfresco.AdvancedSearch", htmlId, ["button", "container"]);
     
      Bubbling.on("beforeFormRuntimeInit", this.onBeforeFormRuntimeInit, this);
      Bubbling.on("afterFormRuntimeInit", this.onAfterFormRuntimeInit, this);
     
      return this;
   };
  
   YAHOO.extend(Alfresco.AdvancedSearch, Alfresco.component.Base,
   {
      /**
       * Object container for initialization options
       *
       * @property options
       * @type object
       */
      options:
      {
         /**
          * Current siteId
          *
          * @property siteId
          * @type string
          */
         siteId: "",
        
         /**
          * Search Form objects, for example:
          * {
          *    id: "advanced-search",
          *    type: "cm:content",
          *    label: "Content",
          *    description: "All types of content"
          * }
          *
          * @property searchForms
          * @type Array
          */
         searchForms: [],
        
         /**
          * Previously saved query, if any
          *
          * @property savedQuery
          * @type string
          */
         savedQuery: "",
        
         /**
          * It is possible to disable searching entire repo via config
          *
          * @property searchRepo
          * @type boolean
          */
         searchRepo: true
      },
     
      /**
       * Currently visible Search Form object
       */
      currentForm: null,
     
      /**
       * Fired by YUI when parent element is available for scripting.
       * Component initialisation, including instantiation of YUI widgets and event listener binding.
       *
       * @method onReady
       */
      onReady: function ADVSearch_onReady()
      {
         var me = this,
            domId = this.id + "-form-list",
            elList = Dom.get(domId);
        
         // see if a saved query json string is provided
         var defaultForm = this.options.searchForms[0];
         if (this.options.savedQuery.length !== 0)
         {
            var savedQuery = YAHOO.lang.JSON.parse(this.options.savedQuery);
            if (savedQuery.datatype)
            {
               for (var f in this.options.searchForms)
               {
                  var form = this.options.searchForms[f];
                  if (form.type === savedQuery.datatype)
                  {
                     // found previous form datatype - use as first form to display
                     defaultForm = form;
                     break;
                  }
               }
            }
         }
        
         // search YUI button and menus
         this.widgets.searchButton1 = Alfresco.util.createYUIButton(this, "search-button-1", this.onSearchClick);
         this.widgets.searchButton2 = Alfresco.util.createYUIButton(this, "search-button-2", this.onSearchClick);
         this.widgets.exportExcelButton = Alfresco.util.createYUIButton(this, "export-excel-button", this.exportToEXCEL());

         this.widgets.formButton = Alfresco.util.createYUIButton(this, "selected-form-button", function(p_sType, p_aArgs)
         {
            // update selected item menu button label
            var form = this.options.searchForms[p_aArgs[1].index];
            this.widgets.formButton.set("label", form.label);
            this.widgets.formButton.set("title", form.description);

            // render the appropriate form template
            this.renderFormTemplate(form);
         },
         {
            label: defaultForm.label,
            title: defaultForm.description,
            type: "menu",
            menu: "selected-form-list"
         });

         // render initial form template
         this.renderFormTemplate(defaultForm, true);
        
         // register the "enter" event on the search text field
         var queryInput = Dom.get(this.id + "-search-text");
         this.widgets.enterListener = new YAHOO.util.KeyListener(queryInput,
         {
            keys: YAHOO.util.KeyListener.KEY.ENTER
         },
         {
            fn: me._searchEnterHandler,
            scope: this,
            correctScope: true
         }, "keydown").enable();
        
         // Finally show the component body here to prevent UI artifacts on YUI button decoration
         Dom.setStyle(this.id + "-body", "visibility", "visible");
      },

      /**
       * DEFAULT ACTION EVENT HANDLERS
       * Handlers for standard events fired from YUI widgets, e.g. "click"
       */
     
      /**
       * Loads or retrieves from cache the Form template for a given content type
       *
       * @method renderFormTemplate
       * @param form {Object} Form descriptor to render template for
       * @param repopulate {boolean} If true, repopulate form instance based on supplied data
       */
      renderFormTemplate: function ADVSearch_renderFormTemplate(form, repopulate)
      {
         // update current form state
         this.currentForm = form;
         this.currentForm.repopulate = repopulate;
        
         var containerDiv = Dom.get(this.id + "-forms");
        
         var visibleFormFn = function()
         {
            // hide visible form if any
            for (var i=0, c=containerDiv.children; i<c.length; i++)
            {
               if (!Dom.hasClass(c, "hidden"))
               {
                  Dom.addClass(c, "hidden");
                  break;
               }
            }
           
            // display cached form element
            Dom.removeClass(form.htmlid, "hidden");
           
            // reset focus to search input textbox
            Dom.get(this.id + "-search-text").focus();
         };
        
         if (!form.htmlid)
         {
            // generate child container div for this form
            var htmlid = this.id + "_" + containerDiv.children.length;
            var formDiv = document.createElement("div");
            formDiv.id = htmlid;
            Dom.addClass(formDiv, "hidden");
            Dom.addClass(formDiv, "share-form");
           
            // cache htmlid so we know the form is present on the form
            form.htmlid = htmlid;
           
            // load the form component for the appropriate type
            var formUrl = YAHOO.lang.substitute(Alfresco.constants.URL_SERVICECONTEXT + "components/form?itemKind=type&itemId={itemId}&formId={formId}&mode=edit&showSubmitButton=false&showCancelButton=false",
            {
               itemId: form.type,
               formId: form.id
            });
            var formData =
            {
               htmlid: htmlid
            };
            Alfresco.util.Ajax.request(
            {
               url: formUrl,
               dataObj: formData,
               successCallback:
               {
                  fn: function ADVSearch_onFormTemplateLoaded(response)
                  {
                     // Inject the template from the XHR request into the child container div
                     formDiv.innerHTML = response.serverResponse.responseText;
                     containerDiv.appendChild(formDiv);
                    
                     visibleFormFn.call(this);
                  },
                  scope: this
               },
               failureMessage: "Could not load form component '" + formUrl + "'.",
               scope: this,
               execScripts: true
            });
         }
         else
         {
            visibleFormFn.call(this);
         }
      },
     
      /**
       * Repopulate currently displayed Form fields based on saved query data
       *
       * @method repopulateCurrentForm
       */
      repopulateCurrentForm: function ADVSearch_repopulateCurrentForm()
      {
         if (this.options.savedQuery.length !== 0)
         {
            var savedQuery = YAHOO.lang.JSON.parse(this.options.savedQuery);
            var elForm = Dom.get(this.currentForm.runtime.formId);
           
            for (var i = 0, j = elForm.elements.length; i < j; i++)
            {
               var element = elForm.elements;
               var name = element.name;
               if (name != undefined && name !== "-")
               {
                  var savedValue = savedQuery[name];
                  if (savedValue !== undefined)
                  {
                     if (element.type === "checkbox" || element.type === "radio")
                     {
                        element.checked = (savedValue === "true");
                     }
                     else if (name.match("-range$") == "-range")
                     {
                        // found number range?
                        var cntrl = Dom.get(element.id + "-cntrl-min");
                        if (cntrl)
                        {
                           // populate number range elements
                           cntrl.value = savedValue.substring(0, savedValue.indexOf("|"));
                           cntrl = Dom.get(element.id + "-cntrl-max");
                           cntrl.value = savedValue.substring(savedValue.indexOf("|") + 1, savedValue.length);
                           // set range value to the input hidden field
                           cntrl = Dom.get(element.id);
                           cntrl.value = savedValue;                          
                        }
                        else
                        {
                           // probably date range - just set value and control will handle it
                           element.value = savedValue;
                        }
                     }
                     else
                     {
                        // standard html control
                        element.value = savedValue;
                     }
                    
                     // reverse value setting doesn't work with checkboxes or multi-select boxes because of the
                     // hidden field used to store the underlying field value
                     if (element.type === "hidden")
                     {
                        // hidden fields could be a part of a checkbox or similar in the Forms runtime
                        // so look if there is a entry element attached this hidden field and set the value
                        var cntrl = Dom.get(element.id + "-entry");
                        if (cntrl)
                        {
                           switch (cntrl.type)
                           {
                              case "checkbox":
                                 cntrl.checked = (savedValue === "true");
                                 break;
                              default: // "select-multiple" - and potentially others following the same pattern
                                 cntrl.value = savedValue;
                                 break;
                           }
                        }
                     }
                  }
               }
            }
           
            Bubbling.fire("formContentsUpdated");
         }
      },
     
      /**
       * Event handler that gets fired when user clicks the Search button.
       *
       * @method onSearchClick
       * @param e {object} DomEvent
       * @param obj {object} Object passed back from addListener method
       */
      onSearchClick: function ADVSearch_onSearchClick(e, obj)
      {
         // retrieve form data structure directly from the runtime
         var formData = this.currentForm.runtime.getFormData();
        
         // add DD type to form data structure
         formData.datatype = this.currentForm.type;
        
         // build and execute url for search page
         var url = YAHOO.lang.substitute(Alfresco.constants.URL_PAGECONTEXT + "{site}search?t={terms}&q={query}&r={repo}",
         {
            site: (this.options.siteId.length !== 0 ? ("site/" + this.options.siteId + "/") : ""),
            terms: encodeURIComponent(Dom.get(this.id + "-search-text").value),
            query: encodeURIComponent(YAHOO.lang.JSON.stringify(formData)),
            repo: this.options.searchRepo.toString()
         });
        
         window.location.href = url;
      },
     
      /**
       * Event handler called when the "beforeFormRuntimeInit" event is received
       */
      onBeforeFormRuntimeInit: function ADVSearch_onBeforeFormRuntimeInit(layer, args)
      {
         // extract the current form runtime - so we can reference it later
         this.currentForm.runtime = args[1].runtime;
        
         // remove Forms Runtime validators on the advanced search form
           this.currentForm.runtime.validations = {};
        
         // Repopulate current form from url query data?
         if (this.currentForm.repopulate)
         {
            this.currentForm.repopulate = false;
            this.repopulateCurrentForm();
         }
      },

      /**
       * Event handler called when the "afterFormRuntimeInit" event is received
       */
      onAfterFormRuntimeInit: function ADVSearch_onAfterFormRuntimeInit(layer, args)
      {
         // extract the current form runtime - so we can reference it later
         this.currentForm.runtime = args[1].runtime;
         var form = (Dom.get(this.currentForm.runtime.formId));
         Event.removeListener(form, "submit");
         form.setAttribute("onsubmit", "return false;");
      },

      /**
       * Search text box ENTER key event handler
       *
       * @method _searchEnterHandler
       */
      _searchEnterHandler: function ADVSearch__searchEnterHandler(e, args)
      {
         this.onSearchClick(e, args);
      },

      /**
       * Function que exporta los resultados de la busqueda a formato excel
       */
      exportToEXCEL : function exportToEXCEL(e,options)

      {
         var tab_text="<table border='2px'><tr bgcolor='#87AFC6'><td>";
         var textRange; var j=0;
         table = options.datatable; // id of table
         var i,j,k, oData;
         var includeLastColumn=true;
         var aRecs = table.getRecordSet().getRecords(),aCols = table.getColumnSet().keys;
         var aColsLength = aCols.length;
         var aRecsLength = aRecs.length;
         for(i=0; i < aColsLength; i++)
         {
            tab_text += aCols.label.replace(/( )*/g,"").replace(/<br[^>]*>/g," ") + ( i < aColsLength ? "</td><td>" : "");
         }
         tab_text += "</td></tr><tr><td>";
         for (j=0; j<aRecsLength; j++) {
            oData = aRecs[j].getData();
            for (k=0; k < aColsLength; k++) {
               tab_text += ( oData[aCols[k].key] + ( k < aColsLength ? "</td><td>" : ""));
            }
            tab_text += "</td></tr><tr><td>";
         }
         tab_text=tab_text+"</td></tr></table>";
         tab_text= tab_text.replace(/<A[^>]*>|<\/A>/g, "");//remove if u want links in your table
         tab_text= tab_text.replace(/<img[^>]*>/gi,""); // remove if u want images in your table
         tab_text= tab_text.replace(/<input[^>]*>|<\/input>/gi, ""); // removes input params
         var thisForm = document.createElement('form');
         thisForm.style.display = 'none';
         document.body.appendChild(thisForm);
         var fileName = document.createElement('input');
         fileName.type = 'hidden';
         fileName.name = 'fileName';
         fileName.value = 'DMS Report–'+new Date();
         thisForm.appendChild(fileName);
         var dataTable = document.createElement('input');
         dataTable.type = 'hidden';
         dataTable.name = 'tableData';
         dataTable.value = tab_text;
         thisForm.appendChild(dataTable);
         thisForm.method = 'POST';
         thisForm.action = Alfresco.constants.URL_CONTEXT+"page/csv-download";
         thisForm.submit();
         document.body.removeChild(thisForm);
      }
   });
})();
</javascript>
12 REPLIES 12

Hola de nuevo!

Finalmente si hemos podido sacar el datatable que se utiliza en la pantalla de search de share, pero nos dimos cuenta de que no era lo que necesitábamos. Siguiendo el ejemplo finalmente hemos logrado crear el excel con el listado de los archivos/espacios que devuelve la búsqueda, pero lo que queremos es listar un excel que incluya además del nombre de los espacios/archivos, los valores de los metadatos…. y aquí es donde estoy otra vez parado.

He intentado llamar a la función exportToExcel, de forma que vuelva a ejecutar la última búsqueda y para eso utilizo el valor almacenado de this.options.searchQuery, que contienen el valor de los parámetros de búsqueda ejem:


"{"assoc_cm_contains_added":"","assoc_cm_contains_removed":"","prop_exprec_expDireccionDestinataria":"","prop_exprec_expServicioTecnico":"","prop_exprec_expFechaReclamacion":"","prop_cm_created":"","prop_exprec_expEstado":"","prop_exprec_expDniReclamante":"","prop_exprec_expNombreReclamante":"","prop_cm_name":"","prop_exprec_expFechaEntrada":"","prop_exprec_expAsunto":"","prop_cm_modified":"","prop_cm_accessed":"","prop_exprec_expNumExpediente":"","datatype":"exprec:expediente_reclamaciones"}"


lo he intentado ejecutar en un script de la JavaScript Search API de Alfresco de la siguiente manera

var excelQuery = this.options.searchQuery;

                var def =
                {
                    query: excelQuery,
                    store: "workspace://SpacesStore"
                   

                };
                var origen = search.query(def);


el problema es que nos dice que el elemento "search no está definido".

¿No puedo utilizar la Java Script Search API de Alfresco en estos ficheros search.js de Share?…. ¿Como puedo obtener los nodos de los elementos que forman la pantalla de resultados de la búsqueda de share?

Si me puedes echar una mano con un comentario te lo agradecería.

Gracias Angel!

angelborroy
Community Manager Community Manager
Community Manager
Habéis topado con un problema muy común: la API JavaScript de Alfresco de servidor. Estáis desarrollando código YUI (que es JavaScript cliente) en la aplicación web Share, por lo que no podéis utilizar esta API.

Desde este punto, suele invocarse a la API REST (Web Scripts) para obtener el servicio que necesitas. Te recomiendo que utilices el helper que proporciona Alfresco para realizar este tipo de invocaciones:

         Alfresco.util.Ajax.request(
         {
            url: Alfresco.constants.PROXY_URI_RELATIVE + "slingshot/search?",  // Aquí tus parámetros de búsqueda
            method: "GET",
            responseContentType : "application/json",
            successCallback:
            {
               fn: function(response)
               {
                  // ..
               },
               scope: this
            },
            failureCallback:
            {
               fn: function(response)
               {
                  // ..
               },
               scope: this
            }
         });


Ten en cuenta que es una invocación asíncrona, lo que puede hacer variar tu flujo previsto de trabajo.
Hyland Developer Evangelist

Hola Angel,

   Perdona por la tardanza en contestar y gracias por la ayuda.
Al final logramos hacer lo que pretendíamos de la forma en que nos comentabas. Utilizando la API REST hicimos una llamada igual que la que realizaba el "Search" para recuperar la lista de resultados y a partir de esos datos construir nuestra tabla para exportar a excel.


var myUrl = window.location.href;

Alfresco.util.Ajax.request({
    //realizamos una busqueda con la misma query que utiliza "search"
    url: Alfresco.constants.PROXY_URI_RELATIVE + "slingshot/search?" + myUrl,
    method: "GET",
    responseContentType: "application/json",
    successCallback: {
        fn: function (response) {
            var results = response.json.items;
            // ..

        },

        scope: this

    },

    failureCallback: {

        fn: function (response) {

            // ..

        },

        scope: this

    }

});
Getting started

Tags


Find what you came for

We want to make your experience in Hyland Connect as valuable as possible, so we put together some helpful links.