Excel 如何更改此基于VBA/XSLT的代码,以便将输出写入单个XML文件中
由于前面的问题,我得到了以下代码 代码的意思是迭代一个excelsheet并用单元格内容自动填充XML标记。输出是此Excel工作表中每一行的XML文件 现在,我有一个非常类似的案例,我知道,要完成它,改变不多。我希望我的代码不是为每一行创建一个新的XML文件,而是在同一个XML文件中填充所有内容 我想自动填写此excel表格的内容: 转换为一个XML模板,该模板最初如下所示:Excel 如何更改此基于VBA/XSLT的代码,以便将输出写入单个XML文件中,excel,xml,vba,xslt,Excel,Xml,Vba,Xslt,由于前面的问题,我得到了以下代码 代码的意思是迭代一个excelsheet并用单元格内容自动填充XML标记。输出是此Excel工作表中每一行的XML文件 现在,我有一个非常类似的案例,我知道,要完成它,改变不多。我希望我的代码不是为每一行创建一个新的XML文件,而是在同一个XML文件中填充所有内容 我想自动填写此excel表格的内容: 转换为一个XML模板,该模板最初如下所示: <?xml version="1.0" encoding="UTF-8"?> <Codes>
<?xml version="1.0" encoding="UTF-8"?>
<Codes>
<AreaCodes>
<Area>
<Name></Name>
<Desc/>
<Facility_Area></Facility_Area>
</Area>
</AreaCodes>
</Codes>
<?xml version="1.0" encoding="UTF-8"?>
<Codes>
<AreaCodes>
<Area>
<Name>RA 001</Name>
<Desc/>
<Facility_Area>ZUF</Facility_Area>
</Area>
<Area>
<Name>RA 002</Name>
<Desc/>
<Facility_Area>ZUF</Facility_Area>
</Area>
<Area>
<Name>RA 003</Name>
<Desc/>
<Facility_Area>ZUF</Facility_Area>
</Area>
<Area>
<Name>RA 004</Name>
<Desc/>
<Facility_Area>ZUF</Facility_Area>
</Area>
...
</AreaCodes>
</Codes>
现在,所有内容都放在一个单独的XML文件中
谁能告诉我,我要改变什么?我知道,对于我的VBA代码,我应该将那些save命令移到循环之外,但这不起作用
很抱歉在英语方面遇到了困难,谢谢大家的帮助。我编写了一个VBA类模块
SheetWrapper
:
Private mySheet As Object
Sub Init(sheet)
Set mySheet = sheet
End Sub
Public Property Get Cell(rowIndex, cellIndex)
Cell = CStr(mySheet.Cells(rowIndex, cellIndex).Value)
End Property
这样就可以使用
Sub Param_XSLT_Process()
Dim xmlDoc As New MSXML2.DOMDocument60
Dim xslDoc As New MSXML2.FreeThreadedDOMDocument60
Dim xslTemp As New MSXML2.XSLTemplate60
Dim xslProc As MSXML2.IXSLProcessor
Dim resultDoc As New MSXML2.DOMDocument60
Dim worksheet As Object
Set worksheet = ActiveWorkbook.Worksheets(1)
Dim myWrapper As SheetWrapper
Set myWrapper = New SheetWrapper
myWrapper.Init worksheet
' LOAD XML AND XSL FILES
xmlDoc.async = False
xmlDoc.Load "C:\SomePath\template.xml"
xslDoc.async = False
xslDoc.SetProperty "AllowDocumentFunction", True
xslDoc.Load "C:\SomePath\sheet.xsl"
' INITIALIZE NEEDED OBJECTS
Set xslTemp.stylesheet = xslDoc
Set xslProc = xslTemp.createProcessor()
xslProc.addObject myWrapper, "http://example.com/excel"
xslProc.addParameter "first-row-index", 2, ""
xslProc.addParameter "last-row-index", ActiveWorkbook.Worksheets(1).UsedRange.Rows.Count, ""
xslProc.input = xmlDoc
xslProc.output = resultDoc
xslProc.transform
resultDoc.Save "C:\SomePath\transformation-result.xml"
End Sub
与XSLT一起:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:excel="http://example.com/excel"
exclude-result-prefixes="msxsl excel">
<xsl:param name="sheet"/>
<xsl:param name="first-row-index"/>
<xsl:param name="last-row-index"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:output indent="yes"/>
<xsl:template match="AreaCodes">
<xsl:copy>
<xsl:call-template name="make-areas">
<xsl:with-param name="area" select="Area"/>
<xsl:with-param name="index" select="$first-row-index"/>
<xsl:with-param name="last" select="$last-row-index"/>
</xsl:call-template>
</xsl:copy>
</xsl:template>
<xsl:template name="make-areas">
<xsl:param name="area"/>
<xsl:param name="index"/>
<xsl:param name="last"/>
<xsl:apply-templates select="$area">
<xsl:with-param name="row-index" select="$index"/>
</xsl:apply-templates>
<xsl:if test="$index < $last">
<xsl:call-template name="make-areas">
<xsl:with-param name="area" select="$area"/>
<xsl:with-param name="index" select="$index + 1"/>
<xsl:with-param name="last" select="$last"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="Area">
<xsl:param name="row-index"/>
<xsl:copy>
<xsl:apply-templates>
<xsl:with-param name="row-index" select="$row-index"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="Area/Name">
<xsl:param name="row-index"/>
<xsl:copy>
<xsl:value-of select="excel:get-Cell($row-index, 1)"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Area/Facility_Area">
<xsl:param name="row-index"/>
<xsl:copy>
<xsl:value-of select="excel:get-Cell($row-index, 2)"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我本来希望能够将Excel sheet对象直接传递给XSLT以读取其单元格,但MSXML却没有做到这一点。我将在周一尝试,并给出我的反馈。多谢各位!
Sub Param_XSLT_Process()
Dim xmlDoc As New MSXML2.DOMDocument60
Dim xslDoc As New MSXML2.FreeThreadedDOMDocument60
Dim xslTemp As New MSXML2.XSLTemplate60
Dim xslProc As MSXML2.IXSLProcessor
Dim resultDoc As New MSXML2.DOMDocument60
Dim worksheet As Object
Set worksheet = ActiveWorkbook.Worksheets(1)
Dim myWrapper As SheetWrapper
Set myWrapper = New SheetWrapper
myWrapper.Init worksheet
' LOAD XML AND XSL FILES
xmlDoc.async = False
xmlDoc.Load "C:\SomePath\template.xml"
xslDoc.async = False
xslDoc.SetProperty "AllowDocumentFunction", True
xslDoc.Load "C:\SomePath\sheet.xsl"
' INITIALIZE NEEDED OBJECTS
Set xslTemp.stylesheet = xslDoc
Set xslProc = xslTemp.createProcessor()
xslProc.addObject myWrapper, "http://example.com/excel"
xslProc.addParameter "first-row-index", 2, ""
xslProc.addParameter "last-row-index", ActiveWorkbook.Worksheets(1).UsedRange.Rows.Count, ""
xslProc.input = xmlDoc
xslProc.output = resultDoc
xslProc.transform
resultDoc.Save "C:\SomePath\transformation-result.xml"
End Sub
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:excel="http://example.com/excel"
exclude-result-prefixes="msxsl excel">
<xsl:param name="sheet"/>
<xsl:param name="first-row-index"/>
<xsl:param name="last-row-index"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:output indent="yes"/>
<xsl:template match="AreaCodes">
<xsl:copy>
<xsl:call-template name="make-areas">
<xsl:with-param name="area" select="Area"/>
<xsl:with-param name="index" select="$first-row-index"/>
<xsl:with-param name="last" select="$last-row-index"/>
</xsl:call-template>
</xsl:copy>
</xsl:template>
<xsl:template name="make-areas">
<xsl:param name="area"/>
<xsl:param name="index"/>
<xsl:param name="last"/>
<xsl:apply-templates select="$area">
<xsl:with-param name="row-index" select="$index"/>
</xsl:apply-templates>
<xsl:if test="$index < $last">
<xsl:call-template name="make-areas">
<xsl:with-param name="area" select="$area"/>
<xsl:with-param name="index" select="$index + 1"/>
<xsl:with-param name="last" select="$last"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="Area">
<xsl:param name="row-index"/>
<xsl:copy>
<xsl:apply-templates>
<xsl:with-param name="row-index" select="$row-index"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="Area/Name">
<xsl:param name="row-index"/>
<xsl:copy>
<xsl:value-of select="excel:get-Cell($row-index, 1)"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Area/Facility_Area">
<xsl:param name="row-index"/>
<xsl:copy>
<xsl:value-of select="excel:get-Cell($row-index, 2)"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>