Call .\build.cmd
on Windows or ./build.sh
on other systems.
-
Install DocFx
- Windows :
choco install docfx -y
- MacOS:
brew install docfx
- Windows :
-
Run
docfx docs/docfx.json --serve
to start local copy of site/docs.
Fresh PowerTools for OpenXml
Home Page: https://sergey-tihon.github.io/Clippit/
License: MIT License
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.
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.
The main idea is to add an API for removing all media elements (video, images, etc.) from the file to reduce its size.
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.
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?
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();
}
}
Hi, i have 2 questions i can't find documentation on. (Even the original repos)
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.
<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?
Next version of OpenXmlSDK will allow to unload not needed slides from memory
dotnet/Open-XML-SDK#1122
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);
}
}
}
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
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>```
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>
Hi Sergey
Could you please review and integrate this pull request https://github.com/EricWhiteDev/Open-Xml-PowerTools/pull/2/files into your code base as I stumbled upon the rem issue in fonts. I have the code already locally and have attached it here (no permissions to create branch/pull request). A new nuget packages would be awesome then. Maybe you can also check other pull requests over there to enhance the library
Thanks lot!
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)
FluentPresentationBuilder
class public
Currently textBoxes are missing from the generated HTML when converting a .docx to .html.
I modified the Contract.docx file to add a textbox
but when converting to html, the textbox is missing.
when converting a .docx with a table wrapped around text, the text wrapping is disabled
I've reproduced these scenarios using the sample tests in the repo.
Instead of catching exception and rewriting package in memory
we can use RelationshipErrorRewriter
Flow:
Features:
{{item.Count}}
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.
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);
}
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?
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.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
There is test.docx created from .pdf via PDF Focus .NET library:
HtmlConverter's HTML outcome (test.html.zip) is:
I think the reason of gap between letters is PDF Focus .NET put almost all letter into own <w:r>:
Anyway, I think it is a bug on our HtmlConverter side. Or is there some option to avoid such result?
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.
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 ๐
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.
Data exported using SpreadsheetWriter
should look behave identical to Format as Table
Excel feature.
This will improve user experience and allow to use generated files as a Source in Power BI.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.