Hello Ricky
Did you know a Microsoft Excel spreadsheet that has a 'xlsx' file extension is actually a compressed folder structure, comprised of a collection of XML files? If you change the 'xlsx' extension to 'zip' you will be able view the data content, see example below. You can't do this for earlier versions of Excel (i.e. 'xls'), as this is a proprietary binary format.
C:\Users\Tony\Desktop\Sample_XL_SSheet_XML.zip
| [Content_Types].xml
|
+---_rels
| .rels
|
\---xl
| styles.xml
| workbook.xml
|
+---worksheets
| sheet1.xml
|
\---_rels
workbook.xml.rels
You can read more about Office Open XML, also known as OpenXML or OOXML, in the following web link.
http://www.officeopenxml.com/- WordprocessingML (docx)
- SpreadsheetML (xlsx)
- PresentationML (pptx)
- DrawingML
If you're interested, the schemas for OOXML can be found on the following web site.
https://svn.cesecore.eu/svn/signserver/vendor/openxml4j/current/src/schemas/You can use the 'XML Schema Wizard' add-in within Caché Studio to create the necessary class definitions. I would recommend you download all these schemas onto your workstation first, as the 'sml-sheet.xsd' schema for example references other schemas using a relative path (i.e. all in the same directory level).
Once you've extracted the contents into a folder structure, you can bring the data into Caché using the following code.
Set reader = ##class(%XML.Reader).%New()
Set sc=reader.OpenFile("C:\Users\Tony\Desktop\[your unzipped xlsx file]\xl\worksheets\sheet1.xml")
Do reader.Correlate("worksheet","OOXML.SML.Worksheet")
Write reader.Next(.worksheet,.sc)
Do worksheet.XMLExport(,",indent")
Unfortunately, I do not have any sample code for you to use, but perhaps someone may be willing to help.
Tony
PS: I'm actually doing this process the other way, creating an 'XLSX' file from a global array work file (merging in standard template data), see below.
^OOXML("Templates",some_key,"OOXML.Types")
^OOXML("Templates",some_key,"OOXML.Types","Default",1,"ContentType") = application/vnd.openxmlformats-package.relationships+xml
^OOXML("Templates",some_key,"OOXML.Types","Default",1,"Extension") = rels
^OOXML("Templates",some_key,"OOXML.Types","Default",2,"ContentType") = application/xml
^OOXML("Templates",some_key,"OOXML.Types","Default",2,"Extension") = xml
^OOXML("Templates",some_key,"OOXML.Types","Override",1,"ContentType") = application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml
^OOXML("Templates",some_key,"OOXML.Types","Override",1,"PartName") = /xl/workbook.xml
^OOXML("Templates",some_key,"OOXML.Types","Override",2,"ContentType") = application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml
^OOXML("Templates",some_key,"OOXML.Types","Override",2,"PartName") = /xl/worksheets/sheet1.xml
^OOXML("Templates",some_key,"OOXML.Types","Override",3,"ContentType") = application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml
^OOXML("Templates",some_key,"OOXML.Types","Override",3,"PartName") = /xl/styles.xml
Method CreateContentTypes() As %Status
{
// populate 'OOXML.Types' object
S name="OOXML.Types"
I '$D(^||OOXML(%ID,"Class",name)) Q $$$OK
S sc=..BuildObject(name, $NA(^||OOXML(%ID,"Class",name)), .types)
// create directory path and write '[Content_Types].xml' file
S filepath=..PathName
I '##class(%File).CreateDirectoryChain(filepath) Q $$$ERROR($$$GeneralError,"Cannot create directory chain")
S file=##class(%XML.FileCharacterStream).%New()
S file.Filename=filepath_"/[Content_Types].xml"
S sc=file.WriteLine("<?xml version=""1.0"" encoding=""UTF-8"" standalone=""yes""?>") I $$$ISERR(sc) Q sc
S ns=##class(%XML.Namespaces).%New()
S sc=types.XMLExportToStream(file,"Types",..ExportFormat,ns) I $$$ISERR(sc) Q sc
S sc=file.%Save() I $$$ISERR(sc) Q sc
// increment file counter
S ..Count=..Count+1
Q $$$OK
}
ClassMethod BuildObject(ClassName As %String, Array As %String, ByRef Object As %RegisteredObject = "") As %Status
{
// instantiate class definition and create new object
S cdef=##class(%Dictionary.ClassDefinition).%OpenId(ClassName,,.sc)
I $$$ISERR(sc) Q sc
S Object=$ZOBJCLASSMETHOD(ClassName,"%New")
// walk though properties in class
S count = cdef.Properties.Count()
F i=1:1:count {
S prop=cdef.Properties.GetAt(i)
S data=$D(@Array@(prop.Name)) // get data for property
I 'data CONTINUE // no data defined
I data=1 S $ZOBJPROPERTY(Object,prop.Name)=@Array@(prop.Name) CONTINUE
I prop.Collection="" {
S sc=..BuildObject(prop.Type, $NA(@Array@(prop.Name)), .ObjectSub)
S $ZOBJPROPERTY(Object,prop.Name)=ObjectSub
} ELSE {
S key="" F {
S key=$O(@Array@(prop.Name,key)) I key="" Q
S sc=..BuildObject(prop.Type, $NA(@Array@(prop.Name,key)), .ObjectSub)
S ObjectColl=$ZOBJPROPERTY(Object,prop.Name)
I prop.Collection="list" S sc=$ZOBJMETHOD(ObjectColl,"InsertAt",ObjectSub,key)
I prop.Collection="array" S sc=$ZOBJMETHOD(ObjectColl,"SetAt",ObjectSub,key)
}
}
}
// all done
Q $$$OK