Subtotalizar filas en excel

Post Reply
artu01
Posts: 306
Joined: Fri May 11, 2007 8:20 pm
Location: Lima

Subtotalizar filas en excel

Post 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?
fwh 17.12, harbour 3.2.0, pelles C, bcc7, Ms-Sql
Mike Serra
Posts: 287
Joined: Fri Apr 14, 2006 5:52 pm
Location: Córdoba (España)

Re: Subtotalizar filas en excel

Post 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,
User avatar
cnavarro
Posts: 5792
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: Subtotalizar filas en excel

Post by cnavarro »

Gracias "paisano"
C. Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
Si alguien te dice que algo no se puede hacer, recuerda que esta hablando de sus limitaciones, no de las tuyas.
artu01
Posts: 306
Joined: Fri May 11, 2007 8:20 pm
Location: Lima

Re: Subtotalizar filas en excel

Post by artu01 »

Gracias Mike lo voy a probar y cualquier cosa te molesto
fwh 17.12, harbour 3.2.0, pelles C, bcc7, Ms-Sql
artu01
Posts: 306
Joined: Fri May 11, 2007 8:20 pm
Location: Lima

Re: Subtotalizar filas en excel

Post 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
fwh 17.12, harbour 3.2.0, pelles C, bcc7, Ms-Sql
Mike Serra
Posts: 287
Joined: Fri Apr 14, 2006 5:52 pm
Location: Córdoba (España)

Re: Subtotalizar filas en excel

Post 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,
Mike Serra
Posts: 287
Joined: Fri Apr 14, 2006 5:52 pm
Location: Córdoba (España)

Re: Subtotalizar filas en excel

Post by Mike Serra »

cnavarro wrote:Gracias "paisano"
Buenas Tardes Cristobal, no sabia que eras "paisano"

Un Saludo,
Post Reply