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

magarcia_sm
Star Contributor
Star Contributor
Bueno, os cuento los avances.
  Eh conseguido que aparezca el botón "exportToExcel" al lado del botón "buscar", pero no tengo claro como llamar ahora desde ese botón a mi function para que exporte los resultados encontrados.

El código para exportar a excel es el siguiente. No tengo claro que pasarle como parametros para que sepa los datos que tiene que exportar. ¿Alguien podría ayudarme con esto? Gracias!

Dejo también los archivos y el código para la creación del botón por si le sirve a alguien de ayuda. Smiley Wink


"tomcat\webapps\share\components\search\exportToExcel.js"
<javascript>
(function () {
    /**
     * 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>



"tomcat\webapps\share\WEB-INF\classes\alfresco\site-webscripts\org\alfresco\components\search\search.get.html.ftl"


<div class="yui-u align-right">
     <span id="${el}-export-excel-button" class="yui-button yui-push-button exportToExcel-icon">
        <span class="first-child">
           <button type="button">${msg('button.exportToExcel')}</button>
        </span>
     </span>
</div>





"tomcat\webapps\share\components\search\search.css"


.search .exportToExcel-icon span.first-child
{
   background: url(../images/exportToExcel-icon.png) no-repeat 12px 4px;
   padding-left: 24px;
}




"tomcat\webapps\alfresco\images\icons\exportToExcel-icon.png"

angelborroy
Community Manager Community Manager
Community Manager
¿Qué versión de Alfresco estás utilizando?
Hyland Developer Evangelist

Hola Angel,
Estoy utilizando la 4.2.f

angelborroy
Community Manager Community Manager
Community Manager
Creo que te falta extender/sobreescribir advsearch.js para incluir el código YUI que controla el botón.

Algo así como lo que incluías en la primera entrada

this.widgets.exportExcelButton = Alfresco.util.createYUIButton(this, "export-excel-button", this.exportToEXCEL());
Hyland Developer Evangelist

Gracias por contestar tan rápido.
Estuve haciendo algunas pruebas pero no doy conseguido que el botón haga nada. Incluso probé utilizando la misma función a la que llama el "searchButton", pero ni así.
No se si me estaré dejando algo atrás.

"tomcat\webapps\share\components\search\search.js"
<javascript>

//search YUI button
   this.widgets.searchButton = Alfresco.util.createYUIButton(this, "search-button", this.onSearchClick)
   this.widgets.exportExcelButton = Alfresco.util.createYUIButton(this, "export-excel-button", this.onSearchClick);

</javascript>

angelborroy
Community Manager Community Manager
Community Manager
Supongo que estás modificando directamente los recursos de Alfresco. En tal caso, copia el contenido de tu
search.js
en el archivo
search-min.js
de manera que ambos contenidos sean idénticos.
Hyland Developer Evangelist

Gracias por la ayuda Angel!

Perdón por seguir dando la lata, ahora mi botón ya llama a la función pero según el ejemplo que estoy siguiendo tengo que pasarle a la función la variable options con el objeto "datatable" y estoy teniendo problemas con esto, no encuentro ningún ejemplo por donde guiarme para recuperar el "datatable". ¿Algún consejo?

Muchas gracias!


var options =

{

datatable: // your YUI datatable object

includeLastColumn: true/false

};

angelborroy
Community Manager Community Manager
Community Manager
No sé si te refieres al algo así:


         // DataTable definition
         this.widgets.dataTable = new YAHOO.widget.DataTable(this.id + "-postlist", columnDefinitions, this.widgets.dataSource,
         {
            initialLoad: false,
            dynamicData: true,
            MSG_EMPTY: this._msg("message.loading")
         });


Lo tienes en https://github.com/Alfresco/share/blob/master/share/src/main/webapp/components/blog/postlist.js
Hyland Developer Evangelist

Hola Angel

Estoy mirando tu ejemplo, pero no se si es lo mismo que intento hacer (bueno aunque no sea lo mismo, la verdad es que no entiendo muy bien). Lo que yo prentendo hacer es pillar el datatable que se genera con los resultados de la búsqueda y pasárselo a mi función ExportToExcel ¿Es esto posible? ¿podrías indicarme cómo por favor?.

Lo que voy entendiendo en el ejemplo es que se crea un nuevo datatable, pero se le indican como parámetros unas variables columnDefinitions y le pasamos el parámetro this.widgets.dataSource … al hacer esto según lo pongo en el código… en la función Alfresco.Search.superclass.constructor.call se me queda colgado.


Alfresco.Search = function (htmlId) {
        Alfresco.Search.superclass.constructor.call(this, "Alfresco.Search", htmlId, ["button", "container", "datasource", "datatable", "paginator", "json"]);

        // Decoupled event listeners
        YAHOO.Bubbling.on("onSearch", this.onSearch, this);

        return this;
    };

    YAHOO.extend(Alfresco.Search, Alfresco.component.SearchBase,
        {
            /**
             * Object container for initialization options
             *
             * @property options
             * @type object
             */

            options: {


                datatable: new YAHOO.widget.DataTable(this.id + "-0", columnDefinitions, this.widgets.dataSource,
                    {
                        initialLoad: false,
                        dynamicData: true,
                        MSG_EMPTY: this._msg("message.loading")
                    }),
….
….
….
….
….


¿Lo que se prentende hacer en el código del ejemplo es cargar o crear un nuevo objeto datatable, con los resultados de la búsqueda ejecutada?

Es decir podemos hacer algo como


    options: {
datatable:this.widgets.datatable,
includeLastColumn: true
}


Gracias una vez más!
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.