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

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