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?
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?
#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.Gracias "paisano"
Gracias Mike lo voy a probar y cualquier cosa te molesto
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
&
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,
cnavarro wrote:Gracias "paisano"