Tech Articles


Exporting Datawindows to Excel / Html without losing Format


I have a function called "GuardarAExcel2()" which uses a step datawindow called "d_filafichero". With this function you generate an excel with the same visual aspect as your datawindow. I hope it helps you:

Example of use:

GuardarAExcel2( dw_1, "c:\Report.xls")
GuardarAExcel2( dw_1, "c:\Report.html")

Result in datawindow:

 

Result in Excel:

 

Result in Google Chorme:

 

Working Datawindow:

enter image description here

Function containing code:

enter image description here

 

 
// Esta función activa CSS en el datawindow que se debe generar en formato Excel, haciendo esto
// se mantinen la apariencia visual del dw en el excel.

// **********************************
// CONSIDERACIONES A TENER EN CUENTA 
// **********************************
// - Si existen controles de tipo column o compute superpuestos (unos encima del otro) el SaveAs solo
//   grabará el que esté por encima. Utilizar la función setPosition() si es posible:
//     > Ejemplo: dw.setPosition( 'campo_t', 'header', true )
// - Los objetos deben de estar en el Layer: Band
//	- AYUDA para aplicar formatos especiales:
//     > http://codesnipers.com/?q=excel-compatible-html
//     > https://stigmortenmyre.no/mso/html/excel/xlconformulas.htm

String ls_GenerateCSS
String ls_Border
String ls_NoWrap
String ls_Fila
String ls_Valor
String ls_Temp
String ls_CabeceraHTML
String ls_PieHTML
String ls_NumToStr

Long i
Long ll_TRow
Long ll_Pos
Long ll_PosIni
Long ll_PosFin
Long ll_Row
Long ll_Temp

Boolean lb_Actualizar

ls_CabeceraHTML = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">'
ls_PieHTML = '</html>'
ls_NumToStr = 'x:str'


// Guardar formato CSS actual del datawindow
ls_GenerateCSS = dwDatos.Describe("DataWindow.HTMLTable.GenerateCSS")
ls_Border = dwDatos.Describe("DataWindow.HTMLTable.border")
ls_NoWrap = dwDatos.Describe("DataWindow.HTMLTable.nowrap")

// Aplicar fomato CSS al datawindow
dwDatos.Modify("DataWindow.HTMLTable.GenerateCSS='1'")
dwDatos.Modify("DataWindow.HTMLTable.border='0'")
dwDatos.Modify("DataWindow.HTMLTable.nowrap='1'")

// Grabar el fichero .xls
dwDatos.SaveAs( spRuta, HTMLTable!, TRUE )

// Importar el fichero .xls al d_FilaFichero
ds_datastore dsHTML
dsHTML = CREATE ds_datastore
dsHTML.DataObject = "d_FilaFichero"
dsHTML.ImportFile( Text!, spRuta )

// Procesar línea a línea para:
//   - Añadir en la cabecera: <!DOCTYPE html>
//   - Reemplazar "{;" por "{"
//   - Si hay visibility:hidden reemplazar su valor por espacios, excel no tiene compatibilidad con esto y lo muestra
//			Ejemplo: Original:    <TD NOWRAP CLASS=htmldw9C370 Style='visibility:hidden;'>0202002003</TD>
//						Reemplazado: <TD NOWRAP CLASS=htmldw9C370 Style='visibility:hidden;'>          </TD>
//   - Solución de número entre paréntesis, excel lo convierte a número negativo.
//   - Mantener los ceros a al izquierda, excel los conviete a números.
//   - Quitar referencias a imágenes que no se incluyen:
//       Ejemplo: Original:    <TD NOWRAP CLASS=htmldw152FC><IMG SRC="" border="0" CLASS=htmldw152FC  onClick="{return htmldw.itemClicked(0,-1,'compute_11',0,-1);}" ></TD>
//                Reemplazado: <TD NOWRAP CLASS=htmldw152FC></TD>
//   - Evitar que texto con / lo convierta a fecha

dsHTML.InsertRow(1)
dsHTML.setItem( 1, 'fila', ls_CabeceraHTML )

dsHTML.InsertRow(0)
ll_TRow = dsHTML.RowCount()
dsHTML.setItem( ll_TRow, 'fila', ls_PieHTML )

For i = 1 to ll_TRow
	lb_Actualizar = False
	ls_Fila = dsHTML.getItemString( i, 'fila' )
	
	// Activación del CSS que está desactivado por defecto
	If Pos( ls_Fila, '{;' ) > 0 Then
		ls_Fila = f_global_replace( ls_Fila, '{;', '{' )
		lb_Actualizar = True
	End If
	
	// Visibilidad
	If Pos( ls_Fila, 'visibility:hidden' ) > 0 or Pos( ls_Fila, 'visibility: hidden' ) > 0 Then
		ll_PosIni = Pos( ls_Fila, '>' )
		ll_PosFin = Pos( ls_Fila, '</' )
		If ll_PosIni > 0 and ll_PosFin > 0 Then
			ls_Valor = Mid( ls_Fila, ll_PosIni + 1, (ll_PosFin - ll_PosIni) - 1 )
			If Len( Trim( ls_Valor ) ) > 0 Then
				ls_Fila = f_global_replace( ls_Fila, ls_Valor, Space( Len( ls_Valor ) ) )
				lb_Actualizar = True
			End If
		End If
	End If
	
	// Solución de número entre paréntesis, excel lo convierte a número negativo.
	ll_PosIni = Pos( ls_Fila, '>(' )
	ll_PosFin = Pos( ls_Fila, ')</' )
	If ll_PosIni > 0 and ll_PosFin > 0 Then
		ls_Valor = Mid( ls_Fila, ll_PosIni + 2, (ll_PosFin - ll_PosIni) - 2 )
		If isNumber( ls_Valor ) Then
			ls_Fila = f_global_replace( ls_Fila, ">(", ">&nbsp;(" )
			lb_Actualizar = True
		End If
	End If
	
	// Aplicar formato para matener ceros a la izquierda
	ll_PosIni = Pos( ls_Fila, '>0' )
	ll_PosFin = Pos( ls_Fila, '</' )
	If ll_PosIni > 0 and ll_PosFin > 0 Then
		ls_Valor = Mid( ls_Fila, ll_PosIni + 1, (ll_PosFin - ll_PosIni) - 1 )
		If isNumber( ls_Valor ) Then
			If Dec( ls_Valor ) > 0 Then
				ls_Fila = f_global_replace( ls_Fila, ">0", " " + ls_NumToStr + ">0" )
				lb_Actualizar = True
			End If
		End If
	End If
	
	// Quitar referencia a imágenes que no se incluyen:
	ll_PosIni = Pos( ls_Fila, '<IMG SRC=""' )
	ll_PosFin = Pos( ls_Fila, '</' )
	If ll_PosIni > 0 and ll_PosFin > 0 Then
		ls_Valor = Mid( ls_Fila, ll_PosIni, (ll_PosFin - ll_PosIni) )
		If Len( Trim( ls_Valor ) ) > 0 Then
			ls_Fila = f_global_replace( ls_Fila, ls_Valor, "" )
			lb_Actualizar = True
		End If
	End If
	
	//Evitar que texto con / lo convierta a fecha
	ll_PosIni = Pos( ls_Fila, '>' )
	ll_PosFin = Pos( ls_Fila, '</' )
	If ll_PosIni > 0 and ll_PosFin > 0 Then
		ls_Valor = Mid( ls_Fila, ll_PosIni + 1, (ll_PosFin - ll_PosIni) - 1 )
		If f_cuenta_char( ls_Valor, '/' ) = 1 Then
			ls_Fila = f_global_replace( ls_Fila, ">"+ls_Valor, " " + ls_NumToStr + ">"+ls_Valor )
			lb_Actualizar = True
		End If
	End If
	
	
	If lb_Actualizar Then
		dsHTML.setItem( i, 'fila', ls_Fila )
	End If
Next


// Guardar el d_FilaFichero como Txt con extensión .xls
dsHTML.SaveAs( spRuta, Text!, FALSE )

// Restaurar el formato CSS original del datawindow
dwDatos.Modify("DataWindow.HTMLTable.GenerateCSS='" + ls_GenerateCSS + "'")
dwDatos.Modify("DataWindow.HTMLTable.border='" + ls_Border + "'")
dwDatos.Modify("DataWindow.HTMLTable.nowrap='" + ls_NoWrap + "'")


DESTROY dsHTML
Return 

 

Thank you all. I'm sorry for my English.

Comments (37)
Wednesday, Sep 27 2017

Hola Eduardo G, intento ejecutar tu funcion pero falta el objeto ds_datastore, puedes publicarlo por favor para probar tu funcion saludos.

#31
0

Wednesday, Sep 27 2017

Hola Byron, ds_datastore (UserObject) está heredado de datastore, puedes reemplazarlo por lo siguiente:

Hello Byron, ds_datastore (UserObject) is inherited from datastore, you can replace it with the following:

datastore dsHTML
dsHTML = CREATE datastore
dsHTML.DataObject = "d_FilaFichero"
dsHTML.ImportFile( Text!, spRuta )

Un saludo.

#32
0

Saturday, Oct 07 2017

hello eduardo G,

it's work for me..but all border in cell not view..still loosing format..

#33
0

Friday, Oct 20 2017

Hola.... muchas gracias por el aporte.... en Chrome se ve muy bien... pero en Excel me divide en 2 renglones cada registro.... 

http://i304.photobucket.com/albums/nn178/leviatanMX/reporte.png

#34
0

Wednesday, Oct 25 2017

Hola,
Te ocurre debido a que los objetos column que tienes en el detail no deben de estar a la misma altura o tienes alguno superpuesto a otro. Es muy aconsejable que los objetos no estén uno encima del otro para que funcione correctamente.

Un saludo.

 

Hello. Hi,
It happens to you because the column objects you have in the detail must not be at the same height or you have some superimposed to another. It is highly advisable that the objects are not on top of each other for them to function properly.
A greeting.

#35
0

Tuesday, Nov 28 2017

Buenos dias amigo me sale error en la funcion F_global_replace .

podrias especificar el tipo de valor y sus argumentos. Gracias es muy importante poner a prueba tu funcion 

#36
0

Wednesday, Nov 29 2017

 

//f_global_replace(fuente,buscar,poner)

/*

Argument Type >> Argument Name

string >> source

string >> look_for

string >> replace_with

Return Type string

 

A String Occurrence Search and Replace Routine

The following code demonstrates a string occurrence search and replace routine.

This routine works generically for any string. For example, 

if old_str = "red" and new_str = "green", all occurrences of 

 "red" inside of mystring will be replaced with "green".

*/

int start_pos=1,len_look_for

len_look_for = len(look_for)

 

//find the first occurrence of look_for ...

start_pos = Pos(source,look_for,start_pos)

//only enter the loop if you find whats in look_for

DO WHILE start_pos > 0

//replace look_for with replace_with ...

source = Replace(source,start_pos,Len_look_for,replace_with)

//find the next occurrence of look_for

start_pos = Pos(source,look_for,start_pos+Len(replace_with))

LOOP

return source

 

 

 

 


// Función: f_cuenta_char

// Descripción: Cuenta todas las ocurrencias de as_char en  la cadena as_source

// Ambito: publica

// Argumentos: as_source {cadena de la que se desea borrar las ocurrencias de as_char}

//    as_char   {caracter a ser contado de la cadena as_source}

// Retorna: Integer {numero de ocurrencias encontradas}

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

int li_pos

int ncuenta=0

 

li_pos = Pos (as_source, as_char, 1)

do while li_pos > 0

ncuenta+=1

as_source = Left (as_source, li_pos - 1) + &

Right (as_source, Len (as_source) - li_pos)

li_pos = Pos (as_source, as_char, 1)

loop

 

return ncuenta

#37
0

Wednesday, Nov 29 2017

Ya lo tienes :-D

#38
0

Friday, Jan 12 2018

Hello, it does not respect custome date format for datetime columns. Could you help please?

Thanks

#39
0

Monday, Jan 15 2018

Hello, check the block "// Prevent text with / convert to date" to adapt it to your needs.
A greeting.

#40
1

Find Articles by Tag

HTTPClient DataWindow JSON Array SVN REST UI Charts Data Migration License Transaction Linux OS MessageBox Database Object OAuth 2.0 PowerServer Mobile Performance Testing Database Connection Android Automated Testing .NET DataStore WebBrowser CoderObject PBDOM JSONGenerator Messagging Application Outlook Source Control DevOps Azure Configuration Expression PDF External Functions TreeView Oracle Icon Text InfoMaker GhostScript TortoiseGit File Platform UI Modernization Branch & Merge Event Web Service Proxy Menu PowerBuilder Database Table RichTextEdit Control PFC RESTClient Variable Window JSONParser SnapDevelop Filter Class Encryption Debugger XML IDE Windows OS OLE iOS TFS PowerScript (PS) Source Code WinAPI DragDrop Event Handling Mobile Database Painter Repository .NET Assembly Interface Debugging Database Table Schema Model Database Trial Service Git SqlExecutor OrcaScript 64-bit TLS/SSL PowerBuilder Compiler Script JSON Debug SqlModelMapper BLOB Deployment Windows 10 Icons SDK Web API RibbonBar Builder Authentication SQL Jenkins Syntax API ActiveX ODBC SnapObjects Validation 32-bit Elevate Conference Bug DLL Database Table Data CrypterObject RibbonBar Open Source PDFlib DataType SOAP .NET Std Framework Resize C# PowerServer Web Import DataWindow PostgreSQL Error Sort Stored Procedure Export SQL Server Encoding Event Handler UI Themes Authorization PostgreSQL ODBC driver OAuth Database Profile Installation NativePDF Import JSON COM Graph Excel PowerBuilder (Appeon) Design Export JSON CI/CD