Code Monkey home page Code Monkey logo

Comments (8)

IvanDrag0 avatar IvanDrag0 commented on May 13, 2024 1

@sergey-tihon Works perfectly! Thank you!

from clippit.

sergey-tihon avatar sergey-tihon commented on May 13, 2024

@IvanDrag0 Can you please be move specific about the functionality you are talking about or share full code snippet?

from clippit.

IvanDrag0 avatar IvanDrag0 commented on May 13, 2024

@sergey-tihon, here's a small Powershell script that just loads the assemblies and applies the data found in an XML file to the document (based on the Open-XML-PowerTools example):

Add-Type -Path "$PSScriptRoot\DocumentFormat.OpenXml.dll"
Add-Type -Path "$PSScriptRoot\Clippit.dll"

[xml]$Data = Get-Content -Path "$PSScriptRoot\Data.xml"

[Clippit.WmlDocument]$WmlDocument = [Clippit.WmlDocument]::FromDocument("$PSScriptRoot\TemplateDocument.docx")

[ref]$templateError = $null

[Clippit.WmlDocument]$wmlAssembledDoc = [Clippit.Word.DocumentAssembler]::AssembleDocument($WmlDocument, $Data, $templateError)

$wmlAssembledDoc.SaveAs("$PSScriptRoot\AssembledDocument.docx")

I'm using the following XML data:

<?xml version="1.0" encoding="utf-8"?>
<Customer>
  <Orders>
    <Order Number="1">
      <Names>
        <Name>John Smith</Name>
        <Name>Johnny Smith</Name>
        <Name>Jon Smith</Name>
      </Names>
      <ProductDescription>Unicycle</ProductDescription>
      <Quantity>3</Quantity>
    </Order>
    <Order Number="2">
      <Names>
        <Name>Jane Smith</Name>
        <Name>Jenny Smith</Name>
        <Name>Jannifer Smith</Name>
      </Names>
      <ProductDescription>Tricycle</ProductDescription>
      <Quantity>8</Quantity>
    </Order>
  </Orders>
</Customer>

The attached Word document shows what I'm trying to do and the results.

It looks like adding any of the command tags/functions inside the <Table> function will result in an invalid Word document (which Word can't open) because the library adds the literal tags into the document.xml file inside the Word DOCX package:

code

AssembledDocument.docx

TemplateDocument.docx

from clippit.

sergey-tihon avatar sergey-tihon commented on May 13, 2024

I do not familiar with this part of the library, but

Here is the code that generate markup for table cell -

var cellRun = paragraph.Elements(W.r).FirstOrDefault();
var xPath = paragraph.Value;
string newValue;
try
{
newValue = EvaluateXPathToString(d, xPath, false);
}

It looks like it should be possible to concatenate multiple xpath results into one string and then generate one paragraph from this string -

if (xPathSelectResult is IEnumerable enumerable and not string)
{
var selectedData = enumerable.Cast<XObject>();
if (!selectedData.Any())
{
if (optional) return string.Empty;
throw new XPathException($"XPath expression ({xPath}) returned no results");
}
if (selectedData.Count() > 1)
{
throw new XPathException($"XPath expression ({xPath}) returned more than one node");
}
switch (selectedData.First())
{
case XElement xElement:
return xElement.Value;
case XAttribute attribute:
return attribute.Value;
}
}

from clippit.

IvanDrag0 avatar IvanDrag0 commented on May 13, 2024

Thank you! I'll give it a try!

from clippit.

IvanDrag0 avatar IvanDrag0 commented on May 13, 2024

My C# is a bit rusty, but I've modified the EvaluateXPathToString function to the following:

private static string EvaluateXPathToString(XElement element, string xPath, bool optional )
{
    object xPathSelectResult;
    try
    {
        //support some cells in the table may not have an xpath expression.
        if (string.IsNullOrWhiteSpace(xPath)) return string.Empty;

        string[] xPathSplit = xPath.Split('/');

        if (element.Descendants(xPathSplit.Last()).Count() > 1)
        {
            var result = element.Descendants(xPathSplit[xPathSplit.Length - 2]).Select(hl => new
            {
                Str = String.Join(", ", hl.Elements(xPathSplit.Last()).Select(x => x.Value))
            });

            var e = new XElement(xPathSplit.Last(), result.First().Str);

            element.Descendants(xPathSplit.Last()).Remove();

            element.Element(xPathSplit[xPathSplit.Length - 2]).Add(e);

        }

        xPathSelectResult = element.XPathEvaluate(xPath);

    }
    catch (XPathException e)
    {
        throw new XPathException("XPathException: " + e.Message, e);
    }

    if (xPathSelectResult is IEnumerable enumerable and not string)
    {
        var selectedData = enumerable.Cast<XObject>();
        if (!selectedData.Any())
        {
            if (optional) return string.Empty;
            throw new XPathException($"XPath expression ({xPath}) returned no results");
        }

        switch (selectedData.First())
        {
            case XElement xElement:
                return xElement.Value;
            case XAttribute attribute:
                return attribute.Value;
        }
    }

    return xPathSelectResult.ToString();
}

This changes the XML in memory to the following, before applying it to the document:

<?xml version="1.0" encoding="utf-8"?>
<Customer>
  <Orders>
    <Order Number="1">
      <Names>
        <Name>John Smith, Johnny Smith, Jon Smith</Name>
      </Names>
      <ProductDescription>Unicycle</ProductDescription>
      <Quantity>3</Quantity>
    </Order>
    <Order Number="2">
      <Names>
        <Name>Jane Smith, Jenny Smith, Jannifer Smith</Name>
      </Names>
      <ProductDescription>Tricycle</ProductDescription>
      <Quantity>8</Quantity>
    </Order>
  </Orders>
</Customer>

The two things that should be added are:

  1. Add another "separator" input parameter to the function to allow the user to use custom joining separators.
  2. Add logic to allow the user to add a new line separator (such as "<w:br/>").

from clippit.

sergey-tihon avatar sergey-tihon commented on May 13, 2024

Just release 1.8.0-beta1 that support multi-value xpath inside table cell as described in #39.

@IvanDrag0 can you please take a look/try and confirm that it cover your use case?

from clippit.

sergey-tihon avatar sergey-tihon commented on May 13, 2024

Released in 1.8.0

from clippit.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.