Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Foxy XLS
Message
Information générale
Forum:
Visual FoxPro
Catégorie:
Classes - VCX
Titre:
Versions des environnements
Visual FoxPro:
VFP 9 SP2
Divers
Thread ID:
01556385
Message ID:
01556889
Vues:
219
Looks like a great tool. Here is another approach that just converts an open DBF or cursor to an XML file and then renames it to XLS.
In Excel 2010 you will get a warning saying that the file type is really not an XLS.
Maybe leaving it with the XML extension might work better (it all depends on what app the user's machine
has associated with opening XML files).
*!*	zVfp_To_Excel_XML.prg
*!*	Kevin V. Emmrich (based on prior work by Christof Wollenhaupt)
*!*	www.jkt9000.com
*!*	Probably make a nice class so it is easier to set widths, fonts, colors, shading, etc -- but this is quick and dirty
*!*	I used the article by Christof Wollenhaupt at http://www.foxpert.com/docs/excel.en.htm as my starting point (he did most of the hard work!).

LPARAMETERS lcCursorDBF, lcXLSFileName
*** lcCursor is open and the alias is passed
*** lcXLSFilename is the the xls file we are creating The full path and name have been passed.
IF TYPE("lcCursorDBF") = "L" OR TYPE("lcXLSFileName") = "L"   && didn't pass what we needed!
	WAIT WINDOW 'goodbye'  && this will causes errors so gotta trap better.
	RETURN
ENDIF

*** Test XLS creation
Local lcFile
Local lcRows, lnField, luValue, lcStyle, lcData
Set Point To "."   && I never used this before!
*** Can I get by with just three styles? a) headers row --21 , b) large text fields --22, c) everything else -- 23
*!*	TEXT TO XmlHeader
*!*	<?xml version="1.0"?>
*!*	<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
*!*	 xmlns:x="urn:schemas-microsoft-com:office:excel"
*!*	 xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
*!*	endtext
*!*	TEXT TO lcStyles
*!*	 <Styles>
*!*	  <Style ss:ID="Default" ss:Name="Normal">
*!*	   <Alignment ss:Vertical="Bottom"/>
*!*	  </Style>
*!*	 <Style ss:ID="s21">
*!*	   <Alignment ss:Vertical="Bottom"/>
*!*	   <Font ss:Size="12" ss:Bold="1"/>
*!*	  </Style>
*!*	  <Style ss:ID="s22">
*!*	   <Alignment ss:Vertical="Bottom" ss:WrapText="1"/>
*!*	  </Style>
*!*	   <Style ss:ID="s23" ss:Name="Normal">
*!*	   <Alignment ss:Vertical="Bottom"/>
*!*	  </Style>
*!*	</Styles>
*!*	endtext


lcXMLFile = lcXLSFileName  && has to be passed
*!*	lcXMLFile = "c:\temp\wcAttachments\" + lcStemName+ ".xls"
If File(m.lcXMLFile)
	Erase (m.lcXMLFile)
Endif

*** I am testing for all these fields, but I have not really run into data yet with Q or V - there are potential errors
*** Currency caused an error since it sent the "$" along and excel didn't like that as a number
*!*	Field Types
*!*	BLOB 			= 	W
*!*	Char 			= 	C
*!*	Char(Binary)	= 	C
*!*	Currency		= 	Y
*!*	Date          	=	D
*!*	DATETIME		=	T
*!*	DOUBLE 			=	B
*!*	FLOAT 			=	F
*!*	GENERAL 		=	G
*!*	INTeger			=	I
*!*	INTeger AutoInc	        =	I
*!*	LOGICAL 		=	L
*!*	MEMO 			=	M
*!*	Number			=	N
*!*	VARBINary		=	Q
*!*	VarChar			=	V

SELECT (lcCursorDBF)  &&  open alias passed from calling program
Set Deleted On
LOCATE

***********************  First do columns widths based on type and expected field sizes  *****************************
*** Let's determine the column widths and such
*!*	IF Character AND 10 OR less in width (or numeric) use 	==>    	<Column ss:AutoFitWidth="0" ss:Width="80"/>
*!*	IF character AND less than 40 use						==>    	<Column ss:AutoFitWidth="0" ss:Width="160"/>
*!*	IF character AND bigger than 40 use memo below (later)	==>		<Column ss:AutoFitWidth="0" ss:Width="160"/>
*!*	IF memo use												==>		<Column ss:StyleID="s21" ss:AutoFitWidth="0" ss:Width="240"/>
m.lcColumns = ""
For lnField = 1 To Fcount()
	lcFieldName = Field(m.lnField)
	Do Case
	Case Type(Field(lnField))$"C" And Fsize(Field(lnField)) <11
		m.lcColumns = m.lcColumns  + [<Column ss:AutoFitWidth="0" ss:Width="80"/>] + Chr(013)
	Case Type(Field(lnField))$"CQV"  && AND FSIZE(FIELD(lnField)) <40
		m.lcColumns = m.lcColumns  + [<Column ss:AutoFitWidth="0" ss:Width="160"/>]  + Chr(013)
*!*		Case Type(Field(lnField))$"CQV"  AND FSIZE(FIELD(lnField)) >40     && no time to test this situation yet
*!*			m.lcColumns = m.lcColumns  + [<Column ss:AutoFitWidth="0" ss:StyleID="s22" ss:Width="213.75"/>]  + Chr(013)
	Case Type(Field(lnField))$"M"  && AND FSIZE(FIELD(lnField)) >40
		m.lcColumns = m.lcColumns  + [<Column ss:AutoFitWidth="0" ss:StyleID="s22" ss:Width="240"/>]  + Chr(013)
	Otherwise
		m.lcColumns = m.lcColumns  + [<Column ss:AutoFitWidth="0" ss:Width="160"/>]  + Chr(013)
	Endcase
ENDFOR

*****************/  End columns  **************************************************************************************

***************** Header Row (table column names)  **************************************************************************************

lcRows = ""
*** Let's Do the Header Row
lcRows = m.lcRows + "<Row>"
For lnField = 1 To Fcount()
	lcFieldName = PROPER(Field(m.lnField))
	lcStyle = [<Cell ss:StyleID="s21">]
	lcData = [<Data ss:Type="String">]+Strconv(Alltrim(m.lcFieldName),9)+[</Data>]
	lcRows = m.lcRows + ;
		lcStyle+m.lcData+[</Cell>]
Endfor
lcRows = m.lcRows + "</Row>"

***************** /Header Row  **************************************************************************************

***************** and here is all the data rows  **************************************************************************************
Scan
	lcRows = m.lcRows + "<Row>"
	For lnField = 1 To Fcount()
		luValue = Evaluate(Field(m.lnField))
		Do Case
		CASE ALLTRIM(UPPER(Field(m.lnField))) == UPPER("Timestamp_Column") OR ALLTRIM(UPPER(Field(m.lnField))) == UPPER("cPassword")
			lcString = SPACE(5)    && let's remove any illegal characters that will confuse the simple XML -- like "<>"
			lcData = ;
				[<Cell ss:StyleID="s23">]+[<Data ss:Type="String">]+lcString+[</Data>]+[</Cell>]
		Case Inlist(type(Field(m.lnField)),"C","Q","V")
*!*	       STRCONV(,9) = STRCONV(,9) - 1 the 9 Converts double-byte characters in cExpression to UTF-8
			lcString = Strconv(Alltrim(m.luValue),9)    && let's remove any illegal characters that will confuse the simple XML -- like "<>"
			lcString = zRemoveEscapeChars(lcString)
			lcData = ;
				[<Cell ss:StyleID="s23">]+[<Data ss:Type="String">]+lcString+[</Data>]+[</Cell>]
		Case Inlist(type(Field(m.lnField)),"M")
			lcString = Strconv(Alltrim(m.luValue),9)    && let's remove any illegal characters that will confuse the simple XML -- like "<>"
			lcString = zRemoveEscapeChars(lcString)
			lcData = ;
				[<Cell ss:StyleID="s22">]+[<Data ss:Type="String">]+lcString+[</Data>]+[</Cell>]
		Case Inlist(type(Field(m.lnField)),"L")
			lcData = ;
				[<Cell ss:StyleID="s23">]+[<Data ss:Type="String">]+IIF(Transform(m.luValue)==".T.","TRUE","FALSE")+[</Data>]+[</Cell>]
		Case Inlist(type(Field(m.lnField)),"N","B","F","I")
			lcData = ;
				[<Cell ss:StyleID="s23">]+[<Data ss:Type="Number">]+Transform(Nvl(m.luValue,0))+[</Data>]+[</Cell>]
		Case Inlist(type(Field(m.lnField)),"Y")
			lcData = ;
				[<Cell ss:StyleID="s23">]+[<Data ss:Type="String">]+Transform(Nvl(m.luValue,0))+[</Data>]+[</Cell>]
		Case Inlist(type(Field(m.lnField)),"D","T")
			luValue	=	LEFT(Transform(Nvl(m.luValue,"")),10)
			lcData = ;
				[<Cell ss:StyleID="s23">]+[<Data ss:Type="String">]+luValue+[</Data>]+[</Cell>]
		Otherwise
			LOOP   && skipping blobs and generals
		ENDCASE
		lcRows = m.lcRows +m.lcData		
*!*			lcRows = m.lcRows +	[<Cell ss:StyleID="]+m.lcStyle+[">]+m.lcData+[</Cell>]
	Endfor
	lcRows = m.lcRows + "</Row>"
ENDSCAN

***************** /Data Rows  **************************************************************************************

**************** OK, let's build the XML file and strtoFile() if XLS (or XLSX) **************************************************************************************
Local lcXML

TEXT to m.lcXML Noshow Textmerge
<?xml version="1.0"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
 xmlns:x="urn:schemas-microsoft-com:office:excel"
 xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet">
 <Styles>
  <Style ss:ID="Default" ss:Name="Normal">
   <Alignment ss:Vertical="Bottom"/>
  </Style>
 <Style ss:ID="s21">
   <Alignment ss:Vertical="Bottom"/>
   <Font ss:Size="12" ss:Bold="1"/>
  </Style>
  <Style ss:ID="s22">
   <Alignment ss:Vertical="Bottom" ss:WrapText="1"/>
  </Style>
   <Style ss:ID="s23">
   <Alignment ss:Vertical="Bottom"/>
  </Style>
</Styles>
  <Worksheet ss:Name="Sheet1">
   <Table><<m.lcColumns>><<m.lcRows>></Table>
  </Worksheet>
  <!-- Placeholder for Additional Sheet -->
</Workbook>
ENDTEXT

Strtofile(m.lcXML,m.lcXMLFile)

return

***********************************************************************************
function zRemoveEscapeChars()
Lparameter cpassedtext

*!*	**** Important Note:  Probably have to check for xml control characters like <,>,&, "
*!*	When writing parsed data to XML: 
*!*	quote (") -->  &quot; 
*!*	apostrophe (') -->   &apos; 
*!*	ampersand (&) -->   &amp; 
*!*	less than (<) -->   &lt; 
*!*	greater than (>) -->   &gt; 
*!*	slash (\) -->   No escape required 
*!*	space  -->  No escape required 


*!*	When writing unparsed data to XML:  
*!*	quote (") -->   \" 
*!*	apostrophe (') -->   &apos; 
*!*	ampersand (&) -->   &amp; 
*!*	less than (<) -->   &lt; 
*!*	greater than (>) -->   &gt; 
*!*	slash (\) -->   \\ 
*!*	space -->   No escape required 

If "&" $ cpassedtext
	cpassedtext = STRTRAN(TRIM(cpassedtext),"&","&amp;")
Endif
If  ">" $ cpassedtext
	cpassedtext = STRTRAN(cpassedtext,">","&gt;")
Endif
If "<" $ cpassedtext
	cpassedtext = STRTRAN(cpassedtext, "<", "&lt;")
Endif


Return cpassedtext
Kevin Emmrich
www.jkt9000.com
Précédent
Répondre
Fil
Voir

Click here to load this message in the networking platform