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

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