Code Monkey home page Code Monkey logo

clippit's Introduction

clippit's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

clippit's Issues

StreamHelpers.ComputeHash issue

Strange issue of hash calculation

System.IO.FileFormatException:
   at MS.Internal.IO.Zip.ProgressiveCrcCalculatingStream.Read (WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at MS.Internal.IO.Zip.ZipIOModeEnforcingStream.Read (WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35)
   at System.Security.Cryptography.HashAlgorithm.ComputeHash (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
   at Clippit.StreamHelpers.ComputeHash (Clippit, Version=1.12.0.0, Culture=neutral, PublicKeyToken=2928a30693862cf5)
   at Clippit.ImageData..ctor (Clippit, Version=1.12.0.0, Culture=neutral, PublicKeyToken=2928a30693862cf5)
   at Clippit.PowerPoint.FluentPresentationBuilder.CopyRelatedImage (Clippit, Version=1.12.0.0, Culture=neutral, PublicKeyToken=2928a30693862cf5)
   at Clippit.PowerPoint.FluentPresentationBuilder.CopyRelatedPartsForContentParts (Clippit, Version=1.12.0.0, Culture=neutral, PublicKeyToken=2928a30693862cf5)
   at Clippit.PowerPoint.FluentPresentationBuilder.AppendSlides (Clippit, Version=1.12.0.0, Culture=neutral, PublicKeyToken=2928a30693862cf5)
   at Clippit.PowerPoint.PresentationBuilder.BuildPresentation (Clippit, Version=1.12.0.0, Culture=neutral, PublicKeyToken=2928a30693862cf5)
   at Clippit.PowerPoint.PresentationBuilder.BuildPresentation (Clippit, Version=1.12.0.0, Culture=neutral, PublicKeyToken=2928a30693862cf5)

PresentationBuilder.PublishSlides generates slides with different data

I'm using PresentationBuilder.PublishSlides to generate slides from the original pptx file.
The problem is that this method returns non-deterministic results from run to run: slide's DocumentByteArray has different data - there is a difference in several bytes.

Is it an expected behavior or not? Thanks.

Simple repro code (NET SDK 6.0.100, Clippit 1.8.1):

using System.IO;
using System.Linq;
using Clippit.PowerPoint;
using DocumentFormat.OpenXml.Packaging;
using Xunit;

namespace PptxTest;

public class UnitTest1
{
    [Fact]
    public void PublishSlides_Should_GenerateSameDataInTwoRuns()
    {
        const string filePath = @"use any pptx file path";
        
        var sizesForSlides1 = SplitPptxAndGetByteSizesForSlides(filePath);
        var sizesForSlides2 = SplitPptxAndGetByteSizesForSlides(filePath);

        Assert.Equal(sizesForSlides1, sizesForSlides2);
    }

    private static int[] SplitPptxAndGetByteSizesForSlides(string filePath)
    {
        using var fileContentStream = File.OpenRead(filePath);
        using var document = PresentationDocument.Open(fileContentStream, false);
        var slides = PresentationBuilder.PublishSlides(document, null);

        return slides.Select(slide => slide.DocumentByteArray.Length).ToArray();
    }
}

rowspan causing error Object reference not set to an instance of an object. at Clippit.HtmlToWml.HtmlToWmlConverterCore.AddPseudoCells(XElement html)

Trying to convert a html table to wml and it is throwing errors I believe due to the rowspan, when I remove the rowspan it works fine. Below is the html for the table (I've replaced the table data with test data as it's client sensitive)

	<thead>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" colspan=\"5\" width=\"690\">
			<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; background: #1F497D; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"background: #1F497D; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"background: #1F497D; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"background: #1F497D; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
			<td style=\"background: #1F497D; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" rowspan=\"2\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" rowspan=\"2\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" rowspan=\"2\" width=\"78\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" rowspan=\"2\" width=\"112\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" rowspan=\"7\" width=\"112\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" rowspan=\"2\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" rowspan=\"3\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" rowspan=\"3\" width=\"112\">
				<p>test</p>
				<p>test</p>
				<p>test</p>
				<p>test</p>
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" rowspan=\"3\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" rowspan=\"3\" width=\"112\">
				<p>test</p>
				<p>test</p>
				<p>test</p>
				<p>test</p>
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; background: white; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" rowspan=\"3\" width=\"112\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; background: white; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; background: white; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
		</tr>
		<tr>
			<td style=\"border: solid windowtext 1.0pt; padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"93\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"295\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"78\">
				<p>test</p>
			</td>
			<td style=\"padding: 0cm 1.4pt 0cm 1.4pt;\" width=\"112\">
				<p>test</p>
			</td>
		</tr>
	</thead>
</table>```

PublishSlides: missing ppt/metadata for google presentations

MicrosoftTeams-image (2)
It looks like rId16 was not copied which leads to a broken reference.

<Relationship Id="rId16" Type="http://customschemas.google.com/relationships/presentationmetadata" Target="metadata"/>

ppt/metadata should be copied as well (it is a binary file), or do not use the reference on it at all in ppt/presentation.xml

Structural comparison for layouts during the slides merge

BuildPresentation should do structural comparison for layouts.

It is wrong to rely on assumption that we can compare layouts by theme name + layout name.
Layout can be different and after the merge we will get visually broken slide.

Generate Excel reports based on some/user's template

Flow:

  1. Create report template in Excel and insert placeholders inside
  2. Write a code that connect data and placeholders
  3. Generate new report with data

Features:

  • Support basic types: string, int, float, datetime, string
  • Support multiple workbooks
  • Support some placeholders language {{item.Count}}

DocumentAssembler: Is it possible to to have conditional Table Row? (unrelated) Hidden methods?

Hi, i have 2 questions i can't find documentation on. (Even the original repos)

  1. Is it possible to have a conditional Table Row? For example:

image

I don't want to show Order Date row if it's empty. I can add another boolean into the model indicating if it needs to be shown or not. But i can't figure out if you can add a conditional to the table.

  1. In Another issue i saw something like thisthis:

<Conditional Select="count(./Orders/Order) > 0" Match="True" />

I can't find any documentation on count(..)? Where does it come from? And more importantly, what else is there?

System.Drawing.Common packaging issue

I tried to use Clippit as a replacement for the old OpenXmlPowerTools package (which seems to work fine function wise), but in one place I use it in combination with System.Drawing.Common. In that specific project I was using version 4.7.0 which worked ok with the old package, but with Clippit I get some nuget warning:

Warning	MSB3277	Found conflicts between different versions of "System.Drawing.Common" that could not be resolved.
There was a conflict between "System.Drawing.Common, Version=4.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" and "System.Drawing.Common, Version=4.0.0.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51".
    "System.Drawing.Common, Version=4.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" was chosen because it was primary and "System.Drawing.Common, Version=4.0.0.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" was not.

I had a quick look at the code in your repo, but I am not very familiar with paket. To me it looks like Clippit has a dependency on System.Drawing.Common (as it pulls its as package reference) but does not propagate this in the nuget package dependencies.

Adding textBox and table wrapped around text when converting to HTML

TextBox

Currently textBoxes are missing from the generated HTML when converting a .docx to .html.

I modified the Contract.docx file to add a textbox
image

but when converting to html, the textbox is missing.
image

Tables wrapped around text

when converting a .docx with a table wrapped around text, the text wrapping is disabled
image

Result
image

I've reproduced these scenarios using the sample tests in the repo.

SixLabors.ImageSharp License check

Hi @JimBobSquarePants

Thank you for all the amazing job done with SixLabors.ImageSharp. I personally love this library and level of the compatibility with System.Drawing.* libraries.

I am the maintainer of Clippit (fork of Open-Xml-PowerTools) that was migrated to .NET 6 and System.Drawing layer replaced by SixLabors.ImageSharp libraries.

I would love to keep this library under MIT license and consume the latest versions of ImageSharp.

From what I see in Six Labors Split License it is perfectly legal to use case:

   Works in Source or Object form are licensed to You under the Apache License, Version 2.0 if.

   - You are consuming the Work in for use in software licensed under an Open Source or Source Available license.
   - You are consuming the Work as a Transitive Package Dependency.

I read it as that consumers of this library (who do not directly reference SixLabors.ImageSharp) can use it commercially without buying the Six Labors Commercial License.

Can you please confirm that I understand it correctly?

Feature: Support for custom content controls in DocumentAssembler

Currently, Clippit is capable of performing a number of actions using DocumentAssembler based on the text found in the content controls (Repeat, Table, Image, etc.). While those actions are very encompassing, would it be possible to add a way to either generate custom/additional actions (based on code) or a way to designate a specific word as a "miscellaneous" control that Clippit can read.

For example, instead of using the control to add pre-generated images, I want to be able to add images/diagrams on the fly using something like PlantUML:

Word:

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim. Fusce est.

<Custom PlantUML="./Root/Diagram">

Vivamus a tellus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci. Aenean nec lorem.

XML:

<?xml version="1.0"?>
<Root>
    <Diagram>
        @startuml
        Bob -> Alice : hello
        @enduml
    </Diagram>
</Root>

Result:

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, sit amet commodo magna eros quis urna. Nunc viverra imperdiet enim. Fusce est.

image

Vivamus a tellus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin pharetra nonummy pede. Mauris et orci. Aenean nec lorem.

That would probably also mean that the DocumentAssembler class would need a way to pass those custom functions and/or definitions (such as DocumentAssembler.AddCustom(funcName(), var value)) or a way to specify the code in the document/xml file.

Excel gives error

I am creating 2 worksheets, the first sheet has some information in string format, the second sheet has a datetime in it.

Excel gives an error if create the sheet with string format first and the datetime second.
If I turn around the order, so datetime sheet first and then string format second, it won't give an error.

Below is the C# code I used. (I used Clippit 1.13.5 also tried it on 1.4 and 1.5 and 1.7)


using Clippit.Excel;
using System.Data;

namespace Test_clippit_multiple_worksheets
{
    public partial class Form1 : Form
    {
        string directory;
        
        public Form1()
        {
            InitializeComponent();
            directory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        }

        private void buttonWrong_Click(object sender, EventArgs e)
        {
            var filePath = Path.Combine(directory, $"ExportWrong.xltx");

            var worksheets = new List<WorksheetDfn>();
            Tuple<DataTable, DataTable> datatables = GetDataTables();
            
            worksheets.Add(CreateWorksheet(datatables.Item1));
            worksheets.Add(CreateWorksheet(datatables.Item2));

            CreateDocument(worksheets.ToArray(), filePath);
        }

        private void buttonCorrect_Click(object sender, EventArgs e)
        {
            var filePath = Path.Combine(directory, $"ExportCorrect.xltx");

            var worksheets = new List<WorksheetDfn>();
            Tuple<DataTable, DataTable> datatables = GetDataTables();
            
            //turned around the order, now it is okay... why???
            worksheets.Add(CreateWorksheet(datatables.Item2));
            worksheets.Add(CreateWorksheet(datatables.Item1));

            CreateDocument(worksheets.ToArray(), filePath);
        }

        private Tuple<DataTable, DataTable> GetDataTables()
        {
            DataTable dt1 = new DataTable("sheet1");
            dt1.Columns.Add("col1_string", typeof(string));
            dt1.Columns.Add("col2_string", typeof(string));

            dt1.Rows.Add("Hello", "world");

            DataTable dt2 = new DataTable("sheet2");
            dt2.Columns.Add("col1_date", typeof(DateTime));
            dt2.Columns.Add("col2_int", typeof(int));

            dt2.Rows.Add(DateTime.Now, -1);

            return new Tuple<DataTable, DataTable>(dt1, dt2);
        }

        private WorksheetDfn CreateWorksheet(DataTable dt)
        {
            var columnNames = from column in dt.Columns.Cast<DataColumn>() select column.ColumnName;
            var headerList = GetHeaderList(columnNames);
            var rows = dt.Rows.Cast<DataRow>().Select(j => GetRow(j.ItemArray)).ToArray();
            var worksheet = GetWorksheet(dt.TableName, headerList, rows);
            return worksheet;
        }

        public CellDfn[] GetHeaderList(IEnumerable<string> headers)
        {
            return headers.Select(x => new CellDfn
            {
                Value = x,
                Bold = true,
            }).ToArray();
        }

        public WorksheetDfn GetWorksheet(string name, CellDfn[] headerList, RowDfn[] rows)
        {
            return
                new WorksheetDfn
                {
                    Name = name,
                    ColumnHeadings = headerList,
                    Rows = rows
                };
        }

        public RowDfn GetRow(IEnumerable<object> values)
        {
            return new RowDfn
            {
                Cells = values.Select(x => new CellDfn
                {
                    CellDataType = GetType(x),
                    Value = x,
                    FormatCode = GetFormatCode(x)
                })
            };
        }

        private string GetFormatCode(object value)
        {
            if (value is DateTime)
                return "dd-MM-yyyy";

            return null;
        }

        private CellDataType GetType(object value)
        {
            if (value is bool)
                return CellDataType.Boolean;
            if (value is DateTime date)            
                return CellDataType.Date;
            if (value is string)
                return CellDataType.String;
            
            return CellDataType.Number;
        }

        public void CreateDocument(WorksheetDfn[] worksheets, string filePath)
        {
            var wb = new WorkbookDfn
            {
                Worksheets = worksheets
            };


            byte[] bytes;
            using (var stream = new MemoryStream())
            {
                wb.WriteTo(stream);
                bytes = stream.ToArray();
            }            
            
            File.WriteAllBytes(filePath, bytes);
        }
    }
}

SpreadsheetWriter should be able write directly to MemoryStream

In-memory Excel generation should be possible.

Currently it is possible only using file system

var filePath = Path.GetTempFileName();
try
{
    SpreadsheetWriter.Write(filePath, wb);
    return new MemoryStream(File.ReadAllBytes(filePath));
}
finally
{
    if (File.Exists(filePath))
        File.Delete(filePath);
}

System.IO.FileNotFoundException exception in WmlComparer example

System.IO.FileNotFoundException exception is thrown while running \OpenXmlPowerToolsExamples\WmlComparer01\WmlComparer01.csproj:

   at System.IO.FileStream.ValidateFileHandle(SafeFileHandle fileHandle)
   at System.IO.FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
   at System.IO.File.ReadAllBytes(String path)
   at Clippit.OpenXmlPowerToolsDocument..ctor(String fileName) in c:\GitRepositories\Clippit\OpenXmlPowerTools\PtOpenXmlDocument.cs:line 133
   at Clippit.WmlDocument..ctor(String fileName) in c:\GitRepositories\Clippit\OpenXmlPowerTools\PtOpenXmlDocument.cs:line 355
   at Clippit.WmlComparer01.Main(String[] args) in C:\GitRepositories\Clippit\OpenXmlPowerToolsExamples\WmlComparer01\WmlComparer01.cs:line 24

image

PresentationBuilder doesn't add slide

I am looking for a way to copy a slide from existing opened PresentationDocument document to another also already opened PresentationDocument document. To achieve it I added a new AppendSlide() method into PresentationBuilder. I tried re-use existing code without extra changes:

public static void AppendSlide(PresentationDocument sourceDoc, int sourceSlideNumber, PresentationDocument outputDoc)
{
    RelationshipMarkup ??= GetDefaultRelationshipMarkup();

    var images = new List<ImageData>();
    var mediaList = new List<MediaData>();
    int startIndex = sourceSlideNumber - 1;
    int count = 1;
    bool keepMaster = true;
    AppendSlides(sourceDoc, outputDoc, startIndex, count,
        keepMaster, true, null, images, mediaList);

    CleanupDocument(outputDoc);
}

Here is a sample running in PresentationBuilder01 project:

PresentationDocument sourcePreDoc = PresentationDocument.Open(@"source.pptx", true);
PresentationDocument outputDoc = PresentationDocument.Open(@"output.pptx", true);
// Do my business logic
// ...
var presentation = outputDoc.PresentationPart.Presentation; // it works if we delete this statement
// ...

PresentationBuilder.AppendSlide(sourcePreDoc, 1, outputDoc);

sourcePreDoc.Close();
outputDoc.Close();

Commit changes: https://github.com/adamshakhabov/Clippit/commit/d402e25a265e49fd2c8021c8045fc8881d551b0b


It does not work. But works (the first slide from source.pptx is added to output.pptx) if we delete outputDoc.PresentationPart.Presentation statement.

While debugging I can not detect how reading DocumentFormat.OpenXml.Presentation.Presentation affects on AppendSlide() flow.

Any ideas?

Expose FluentPresentationBuilder

  • Make FluentPresentationBuilder class public
  • Refactors/cleanup implementation
  • Review public API
  • Allow usage on top of not-empty presentation #24

ManageMediaCopy: improvement ideas

After PR #53 method ManageMediaCopy uses Sha256 hash algorithm for duplicate media detection purposes.

But all media is zipped, so it's possible to use Crc32 checksum from every zip entry. This approach could remove unnecessary Sha calculation with an IO operation (read & hash) because Crc32 is already precomputed and available.

ZipArchiveEntry.Crc32 property was added in NetCore2.1, so it's important to use it carefully due to the current target framework (netstandard2.0)

Unfortunately, this property can't be easily accessed, so the only way is to use reflection.

Simple example how it could be used:

private uint GetCrc32(object srcObj)
{
    var packagePart = GetInternalProperty<ZipPackagePart>(srcObj, "PackagePart");
    var zipArchiveEntry = GetInternalProperty<ZipArchiveEntry>(packagePart, "ZipArchiveEntry");
    var crc32 = GetInternalProperty<uint>(zipArchiveEntry, "Crc32");
    return crc32;
}

srcObj might be ImagePart or DataPart.

Rough GetInternalProperty implementation:

private static T GetInternalProperty<T>(object srcObj, string propName)
{
    var prop = srcObj.GetType().GetProperty(propName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
    return (T) prop!.GetValue(srcObj);
}

From my local tests it might improve performance by 15-20% on some large pptx file with many media elements ๐Ÿ˜„

Support multi-value XPath results

I have an XML file that looks like this:

<Document>
    <Paragraph>
        <p>This is text
        <p>This is also text
        <p>And this is text
    </Paragraph>
</Document>

If I wanted to list the

nodes as separate line in a document, I could use the function:

<Repeat Select="./Document/Paragraph"/>
The text is: <./p>
<EndRepeat/>

How would I go about doing something similar in a table (if I want a repeated section in a table cell)? I've tried using the

function, adding the <./p> in the cell and adding <Table Select="./Document/Paragraph"/>, but I get an error stating that there are multiple results. If I add <./Paragraph/p> to the table cell and <Table Select="./Document"/>, the <p> sections are joined together as one big sentence with no spaces between them. If I use the <Repeat> function in the table cell, I get an error as well.

First tab in paragraph is ignorred

First tab in paragraph is ignorred during conversion OpenXml Word file into HTML by WmlToHtmlConverter.ConvertToHtml().
As result layout is corrupted and words are overlaped each other.

OpenXml:

<w:p w14:paraId="1ED11E10" w14:textId="54EA0B67" w:rsidR="008635E7" w:rsidRDefault="008F0094">
      <w:r>
        <w:t>BlaBlaBlaBlaBla</w:t>
      </w:r>
      <w:r>
        <w:tab />
      </w:r>
      <w:r>
        <w:t>Bla</w:t>
      </w:r>
</w:p>

Result HTML:

<div>
      <p dir="ltr" class="pt-Normal">
        <span lang="en-GB" class="pt-DefaultParagraphFont">BlaBlaBlaBlaBla</span>
        <span lang="en-GB" class="pt-DefaultParagraphFont-000000">Bla</span>
      </p>
</div>

FirstTab.docx
FirstTab-html

DocumentAssembler: Text formatting?

I couldn't find a way to format text in the document assembler. rtf/markdown/html or anything? Am i correct in this?

I'm willing to take a stab at it, with some guidance, does it happen anywhere else in the library that i can look how it should be done?

With some formatting, like bold, italic, underline and list would make this killer library.

Slides generated using PresentationBuilder.PublishSlides have original docProps

All slides generated using PresentationBuilder.PublishSlides have the same docProps as the original file.

That's the problem because docProps/app.xml is used by multiple tools to get metadata about the file (like slides count, titles, etc.).

Ideally, this method should generate new props with slide-specific data.

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.