Page 1 of 1

Subtotalizar filas en excel

Posted: Thu Dec 03, 2020 4:45 am
by artu01
Gente:
Necesito subtotalizar filas en excel desde fwh usando alguna de las alternativas de abajo:
1. Podrá hacerse con xbrowse?
2. Algun ejemplo con la clase texcelscript u otra clase?
3. Algun ejemplo con tablas dinámicas?

Re: Subtotalizar filas en excel

Posted: Thu Dec 03, 2020 9:19 am
by Mike Serra
Buenos días Artu01:

Ahora creo que dependiendo de la versión que tengas, hay soluciones a lo que pides. Yo hace mucho tiempo me construí una clase, que en su momento me resolvió el problema que tenía. Te paso un ejemplo de uso y la clase. He sacado el código del fuente que tenía y lo he adaptado para que puedas compilarlo (yo tengo FW1610 / BCC / Compilador correspondiente a la versión). El ejemplo es sencillo. Por cierto, la clase tiene un metodo para ocultar columnas del detalle de datos. Espero que te sirva para lo que necesitas.

Code: Select all

#include "fivewin.ch"

#DEFINE EXCEL_FORMAT_FILE_CSV   6

function main()
   local oExcel,cNombreEmpresa:="Nombre empresa, S.C.A."
   local dDesdeFecha:=CTOD(""),dHastaFecha:=date()
   local aProductos:={;
                            {"001","Descripcion 1",14,3.99,55.86},;
                            {"002","Descripcion 2",1,2.5,2.5};
                     }
   
   oExcel:=tExcelExport():New()
   oExcel:AddTitle({cNombreEmpresa})
   oExcel:AddTitle({"Fecha:" + dtoc(date())})
   oExcel:AddBlankLine()
   oExcel:AddTitle({"Exportación de Productos a Excel:"})
   oExcel:AddTitle({"Desde Fecha:",dtoc(dDesdeFecha),"Hasta Fecha: ",dtoc(dHastaFecha)})
   oExcel:AddBlankLine()
   oExcel:AddHeadTitle({"Codigo", "Descripción","Udes.","Precio M.","Total"})  
   oExcel:SetData(aProductos)
   //oExcel:SetHideColumns({6})
   oExcel:AddColumnsTotals({5})       //Aqui el nº de columnas que tiene que totalizar añades los totales
   oExcel:CreateFile()
return


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class tExcelExport

    data nRow               init 1
    data nColumn            init 1  
    data aTitles            init {}
    data aDatas             init {}
    data aTitles            init {}
    data aHidesColumn       init {}
    data aHeadTitles        init {}
    data aColumnTotals      init {}
    data cPosibleColumnWord INIT "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
    
    data cFileName  init ""
    data oExcel,oSheet,oBook
    
    data lScreenUpdating init .t.
    
    method New()                                                                    // Constructor de la Clase
    method CreateFile(lSave)                                                        // Metodo que construye el excel en base a todo lo especificado. Termina abriendolo y mostrando el fichero
    method SetData(aDatas)                  INLINE ::aDatas:=aDatas                 // Metodo para asignarle un array bidimensional con los datos a mostrar
    method SetHideColumns(aHidesColumn)     INLINE ::aHidesColumn:=aHidesColumn     // Metodo para asignar un array unidimensional con las columnas de los datos que no queremos mostrar
    method ReviewExcel()            
    method SetName(cFileName)               INLINE ::cFileName:=cFileName           // Establecemos un nombre al fichero de salida
    method AddTitle(aValues)                INLINE aadd(::aTitles,aValues)          // Método para añadir lineas de titulo al documento
    method AddBlankLine()                   INLINE aadd(::aTitles,{""})             // Método simple para añadir una linea en blanco (seria como un salto de línea)
    method AddHeadTitle(aHeadTitles)        INLINE ::aHeadTitles:=aHeadTitles       // Metodo para añadir un array unidimensional con los nombre de las cabeceras de los datos
    method AddColumnsTotals(aColumnTotals)  INLINE ::aColumnTotals:=aColumnTotals
    method SetViewUpdating(lView)           INLINE ::lScreenUpdating:=lView
    
end class

///////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////
method New() class tExcelExport
return self

method CreateFile(lSave) class tExcelExport
    local i,x,nTamTitle,nTamTitleElement,nTam,nTamData,nPos,nPosicionComienzoDetalle,nFilasImpresas:=0,cFileName
    local lActivaDobleLetraColumna:=.f.
    default lSave:=.f.
    if !::ReviewExcel()
        msgalert("Microsoft Excel NO instalado. La exportación no se va a llevar a cabo","¡Atención!")
        return
    end if 
    
    ::oExcel:ScreenUpdating := ::lScreenUpdating
    ::oBook:=::oExcel:WorkBooks:Add()
    ::oSheet:=::oExcel:ActiveSheet
    nTamTitle:=len(::aTitles)
    for i = 1 to nTamTitle
        nTamTitleElement:=len(::aTitles[i])
        for x = 1 to nTamTitleElement
            ::oSheet:Cells( ::nRow, ::nColumn):Value:=::aTitles[i,x]
            ::nColumn++
        next x
        ::nColumn:=1
        ::nRow++
    next i  
    
    //Ahora pintamos las cabeceras de las columnas
    nTamData:=len(::aHeadTitles)
    if nTamData>0
        for i = 1 to nTamData
            nPos:=ASCAN(::aHidesColumn,i)
            if nPos = 0
                ::oSheet:Cells( ::nRow, ::nColumn):Value:=::aHeadTitles[i]
                ::nColumn++
            end if
        next i
        //Pintamos una linea de separacion entre lo ultimo impreso y el detalle a imprimir
        ::oSheet:Range( ::oSheet:Cells( ::nRow, 1 ), ::oSheet:Cells( ::nRow, nTamData-len(::aHidesColumn) ) ):Select()
        ::oExcel:Selection:Borders(9):LineStyle := 1   // xlContinuous = 1
        ::oSheet:Rows( ::nRow ):Font:Bold   := .T.
        ::nRow++
        ::nColumn:=1
    end if
    
    //Ahora el detalle
    nPosicionComienzoDetalle:=::nRow
    nTam:=len(::aDatas)
    if nTam>0
        nTamData:=len(::aDatas[1])
        
        for i = 1 to nTam
            for x = 1 to nTamData
                nPos:=ASCAN(::aHidesColumn,x)
                if nPos = 0
                    ::oSheet:Cells( ::nRow, ::nColumn):Value:=::aDatas[i,x]
                    ::nColumn++
                end if
            next x
            ::nColumn:=1
            ::nRow++
        next i
        
        ::oSheet:Range( ::oSheet:Cells( ::nRow-1, 1 ), ::oSheet:Cells( ::nRow-1, nTamData-len(::aHidesColumn) ) ):Select()
        if !lSave //Si se va a crear un fichero, no le ponemos los bordes
            ::oExcel:Selection:Borders(9):LineStyle := 1   // xlContinuous = 1
        end if
        //Vamos a no ajustar el texto en las columnas que sean caracter
        for x = 1 to nTamData
            nPos:=ASCAN(::aHidesColumn,x)
            if nPos = 0
                if valtype(::aDatas[1,x]) = "C"
                    ::oSheet:Range( ::oSheet:Cells( 1, x ), ::oSheet:Cells( ::nRow , x) ):Select()
                    ::oExcel:Selection:WrapText:=.f.
                end if
            end if
        next x
    end if
    
    //AHora vamos a añadir los totales si los hubiera
    for i = 1 to len(::aColumnTotals) 
        nPos:=ASCAN(::aHidesColumn,i)
        if nPos = 0
            if !lActivaDobleLetraColumna
                ::oSheet:Cells(::nRow,::aColumnTotals[i]):Formula:="=SUMA("+substr(::cPosibleColumnWord,::aColumnTotals[i],1)+alltrim(str(nPosicionComienzoDetalle)) + ":"+substr(::cPosibleColumnWord,::aColumnTotals[i],1)+alltrim(str(::nRow-1))+")" // APLICAR FORMULA A UNA CELDA
                if substr(::cPosibleColumnWord,::aColumnTotals[i],1) = "Z"
                    lActivaDobleLetraColumna:=.t.
                end if
            else
                ::oSheet:Cells(::nRow,::aColumnTotals[i]):Formula:="=SUMA(A"+substr(::cPosibleColumnWord,::aColumnTotals[i],1)+alltrim(str(nPosicionComienzoDetalle)) + ":A"+substr(::cPosibleColumnWord,::aColumnTotals[i],1)+alltrim(str(::nRow-1))+")" // APLICAR FORMULA A UNA CELDA
            end if
        end if
    next i
    ::oSheet:Cells(1,1):Select()
    if !lSave
        ::oExcel:Visible:=.t.
    else
        if !empty(::cFileName)
            cFileName:=alltrim(::cFileName)
        else
            cFileName:=".\Excel_Export_" + dtos(date()) + strtran(time(),":","") + ".csv"
        end if
        ::oSheet:SaveAs(cFileName,EXCEL_FORMAT_FILE_CSV)
        ::oBook:Close(.t.)
        msginfo("Se ha generado el fichero " + cFileName,"Información")
    end if
    
return

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
method ReviewExcel() class tExcelExport
    TRY
        ::oExcel:= GetActiveObject( "Excel.Application" )
    CATCH
        TRY
            ::oExcel:= CreateObject( "Excel.Application" )
        CATCH
            return .f.         
        END
    END
return .t.

 
Un Saludo,

Re: Subtotalizar filas en excel

Posted: Thu Dec 03, 2020 12:29 pm
by cnavarro
Gracias "paisano"

Re: Subtotalizar filas en excel

Posted: Thu Dec 03, 2020 4:15 pm
by artu01
Gracias Mike lo voy a probar y cualquier cosa te molesto

Re: Subtotalizar filas en excel

Posted: Thu Dec 03, 2020 6:10 pm
by artu01
Mike
lo que busco es hacer lo mismo que hace la funcion subtotales() de excel, es decir poder expandir o contraer la data tipo arbol jerarquico 2 niveles


http://forums.fivetechsupport.com/viewt ... =6&t=39665

Re: Subtotalizar filas en excel

Posted: Fri Dec 04, 2020 3:23 pm
by Mike Serra
Buenas Tardes Artu01:

Disculpa, no había entendido bien entonces. Con "macros" de Excel se puede hacer, pero desconozco si se puede ejecutar "código VBA" en Excel desde FW. Entre los master del foro pude componer la clase que te escribí antes, esperemos que haya alguien que pueda echarnos una mano.

Un SAludo,

Re: Subtotalizar filas en excel

Posted: Fri Dec 04, 2020 3:24 pm
by Mike Serra
cnavarro wrote:Gracias "paisano"
Buenas Tardes Cristobal, no sabia que eras "paisano"

Un Saludo,