Range.InsertXML using Transform

2019-05-28 19:41发布

I am using Range.InsertXML to add formatted content to an existing MS Word document.

AFAICT, the method .InsertXML takes parameters XML as a string and XLST (Transform) as a variant; however the documentation for .InsertXML is lacking in that it does not provide an example that includes the use of Transform.

In responding to this question: Range.InsertXML throws when inserting Open XML Cindy Meister linked to an excellent resource that explains lotd about Words XML and how to use it, but I still can't find any examples where Transform is used.

What I am trying to do is the same as in this question: XSLT create table with dynamic number of rows and columns (but using VBA).

From that question this is the modified code that I expected to work:

Sub testInsertXML()

    Dim strXML As String
    Dim XSLT As Variant

    strXML = "<Movies><Genre name=""Action""><Movie><Name>Crash</Name><Released>2005</Released></Movie></Genre><Genre name=""Drama""><Movie><Name>The Departed</Name><Released>2006</Released></Movie><Movie><Name>The Pursuit of Happyness</Name><Released>2006</Released></Movie></Genre><Genre name=""Comedy""><Movie><Name>The Bucket List</Name><Released>2007</Released></Movie></Genre></Movies>"

    XSLT = "<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"" xmlns:w=""http://schemas.microsoft.com/office/word/2003/wordml""><xsl:output indent=""yes""/><xsl:template match=""/""><w:document><w:body><w:tbl><w:tr><xsl:for-each select=""/Movies/Genre""><w:tc><w:p><w:r><w:t><xsl:value-of select=""@name""/></w:t></w:r></w:p></w:tc></xsl:for-each></w:tr><!-- Movies? --><xsl:call-template name=""movies-row""><xsl:with-param name=""i"" select=""1""></xsl:with-param></xsl:call-template></w:tbl></w:body></w:document></xsl:template><xsl:template name=""movies-row""><xsl:param name=""i""/><w:tr><xsl:for-each select=""/Movies/Genre""><w:tc><w:p><w:r><w:t><xsl:choose><xsl:when test=""count(Movie) >= $i""><xsl:value-of select=""concat(Movie[$i]/Name, ' (', Movie[$i]/Released, ')')""/></xsl:when><xsl:otherwise><!-- empty cell --></xsl:otherwise></xsl:choose></w:t></w:r></w:p></w:tc></xsl:for-each></w:tr><xsl:if test=""/Movies/Genre[count(Movie) > $i]"">" & _
           "<xsl:call-template name=""movies-row""><xsl:with-param name=""i"" select=""$i + 1""/></xsl:call-template></xsl:if></xsl:template></xsl:stylesheet>"

    Selection.Range.InsertXML strXML, XSLT

End Sub

I have added double quotes to the strings (so that the quotes appear correctly when using debug.print) AND I have added additional tags as described here.

I think I'm not setting up the Transform correctly. If the Transform is set to vbnullstring everything works. Otherwise I get an error:

XML markup cannot be inserted in the specified location

Basically, as an answer to this question, I'd like a minimal example showing how to use .InsertXML using Transform.

1条回答
对你真心纯属浪费
2楼-- · 2019-05-28 20:23

Working solution:

The original source for the xml appears to be from this docs.microsoft.com site. Incidentally, there are also some instructions on how to create an XSLT directly from a MS Word document (well, albeit manually).

At any rate, it's easiest to just to the transform and insert as two separate steps, like this:

Sub xmlTest()
    Dim xData As MSXML2.DOMDocument60
    Dim xTnsf As MSXML2.DOMDocument60
    Dim xOutp As MSXML2.DOMDocument60

    Set xData = New MSXML2.DOMDocument60
    Set xTnsf = New MSXML2.DOMDocument60
    Set xOutp = New MSXML2.DOMDocument60

    xData.Load "C:\Temp\MyMovies.xml"
    xTnsf.Load "C:\Temp\MyMovies.xslt"

    xData.transformNodeToObject xTnsf, xOutp

    ThisDocument.Range.InsertXML xOutp.XML

    Debug.Print xOutp.XML

End Sub
查看更多
登录 后发表回答