Aspose.Words for .NET 21.1 Release Notes

Major Features

There are 78 improvements and fixes in this regular monthly release. The most notable are:

  • StartColumnBookmark and EndColumnBookmark methods were introduced in DocumentBuilder class.
  • MarkdownSaveOptions.ImageSavingCallback has been added to control how images are saved upon converting to Markdown format.
  • Added an ability to ignore <noscript> HTML elements upon loading HTML.
  • TableStyle.VerticalAlignment was exposed publicly.

Full List of Issues Covering all Changes in this Release

Key Summary Category
WORDSNET-4987 Support “cold” rendering of OOXML SmartArt (Diagrams) New Feature
WORDSNET-20666 Add feature to create Move revision New Feature
WORDSNET-21389 Add IImageSavingCallback into MarkdownSaveOptions New Feature
WORDSNET-17026 LINQ Reporting Engine - Support section breaks inside data bands and conditional blocks New Feature
WORDSNET-20367 Add a field to the Node class so a User can store some custom meta-data in Aspose.Words Document model New Feature
WORDSNET-18882 Add feature to bookmark the table’s column New Feature
WORDSNET-21114 Add feature to get or set Cell Vertical Alignment using TableStyle New Feature
WORDSNET-21426 MS Word should automatically pick default Icon of Inserted OLE Object Enhancement
WORDSNET-21576 Add LastChild property and AppendChild() method to StructuredDocumentRangeStart class Enhancement
WORDSNET-21433 Improve URI processing to handle relative hyperlink Enhancement
WORDSNET-21493 Convert Word to JSON in Parent Child Hierarchy Enhancement
WORDSNET-20881 Partial rendering of Arabic Words in PDF Bug
WORDSNET-21005 Document.PageCount hangs for MHTML file generated by Aspose.Email Bug
WORDSNET-18933 DOCX to PDF conversion issue with math equation Bug
WORDSNET-15142 Incorrect page count detection Bug
WORDSNET-21516 First column content spilling into second column in PDF Bug
WORDSNET-17876 Characters (subset) in charts are not rendered in output PDF Bug
WORDSNET-13179 DOCX to PDF conversion issue with text rendering of Cambodian Fonts “Khmer” Bug
WORDSNET-18333 Superscript and Subscript characters in picture are not retained in PDF Bug
WORDSNET-21191 InvalidOperationException occurs during saving to HTML Bug
WORDSNET-16704 BitonalConvertor gives not the same result as on .NET Bug
WORDSNET-17362 Brackets and equation rendering issue in output PDF Bug
WORDSNET-21509 DOCX to PDF conversion exception: System.ArgumentOutOfRangeException Bug
WORDSNET-21415 Document.Compare generates the incorrect output Bug
WORDSNET-17888 Arabic characters are improperly rendered to another font Bug
WORDSNET-17986 Position of BookmarkStart and BookmarkEnd nodes is changed in output DOCX Bug
WORDSNET-21534 Incorrect value of STYLEREF field in header - Word to PDF Conversion Bug
WORDSNET-21535 Aspose.Words.FileCorruptedException is thrown for DOC Bug
WORDSNET-21462 DOCX to HTML conversion fails with Stack empty error message Bug
WORDSNET-21506 Hidden runs located in a Structured Document tag cannot be iterated Bug
WORDSNET-20715 The conversion to PDF never ends Bug
WORDSNET-21510 System.ArgumentOutOfRangeException occurs upon saving to PDF Bug
WORDSNET-21519 DOCX to PDF conversion exception Bug
WORDSNET-21494 Document.UpdateFields throws NullReferenceException Bug
WORDSNET-20010 Infinity loop in FloaterOverlapResolver due to zero height floating table Bug
WORDSNET-21545 Add obfuscation check to ApiTests.License.Net task Bug
WORDSNET-21552 Incorrect identification of list level and list item Bug
WORDSNET-17735 Certain Arabic characters are wrong when converting DOCX to PDF Bug
WORDSNET-20166 Infinity loop in FloaterOverlapResolver Bug
WORDSNET-18940 Conversion issue DOC/DOCX to PDF Bug
WORDSNET-17428 Superscript and Subscript characters in Picture render as question mark in PDF Bug
WORDSNET-21579 Insert SVG image failed on .NetFramework Bug
WORDSNET-21434 DOCX to PDF conversion: The numbering issue in the output Bug
WORDSNET-21253 Unexpected chart type Bug
WORDSNET-20876 SmartArt to PNG conversion issue with wrong background color and wrong font Bug
WORDSNET-21443 LINQ Reporting Engine - An issue with a JSON object having only complex properties Bug
WORDSNET-20892 ODT to Html: Frame borders and position are lost when converting .odt to html Bug
WORDSNET-21116 PDF/A-1a fails accessibility check Bug
WORDSNET-3814 Line numbering shows up in OpenOffice after changing PageSetup settings Bug
WORDSNET-21419 Inline ole shape overlaps container cell border after DOCX to PDF conversion Bug
WORDSNET-21325 Comments date do not reflect to changed time zone Bug
WORDSNET-21453 “Arithmetic operation resulted in an overflow.” exception when converting DOCX file to PNG/HTML/PDF Bug
WORDSNET-20954 Table lost formatting on page extraction Bug
WORDSNET-21268 DOC to PDF conversion hangs Bug
WORDSNET-21460 Bibliography text disappears during conversion Bug
WORDSNET-21153 UpdatePageLayout is throwing Array Dimensions exceeded supported range Bug
WORDSNET-20681 OutOfMemoryException when SaveAs document as PNG Bug
WORDSNET-21173 No content is loaded from a CHM file Bug
WORDSNET-21282 Preserve Text Alignment in Table Cell during Word DOT to HTML Conversion Bug
WORDSNET-21286 DataLabel customization does not work when chart is inserted into template Bug
WORDSNET-21171 FileCorruptedException is thrown when trying to load a CHM document Bug
WORDSNET-21299 Sunburst Chart DOCX to PDF - System.ArgumentException Unexpected chart type Bug
WORDSNET-21476 Aspose.Words corrupts document containing statistical chart Bug
WORDSNET-21481 Comment.DateTime get time in UTC without conversion to local Bug
WORDSNET-21326 Execution of the Aspose.Words hangs on Linux when Tahoma font is absent Bug
WORDSNET-21203 HTML to PDF output incomplete Bug
WORDSNET-21341 3rd level of Thai text is not shown and replaced by strange symbol - DOCX to PDF Bug
WORDSNET-19932 Number list issues while converting DOCX -> HTML -> DOCX Bug
WORDSNET-21216 Diffrent behavior of “=SUM(ABOVE)” compared to Microsoft Word Bug
WORDSNET-21366 DOC->PDF conversion: Heading loses capitalization and bold effect in the output Bug
WORDSNET-16770 Image’s text is rendered as “?” mark in output PDF Bug
WORDSNET-14872 Lack of CSS background images while converting from HTML to Word Bug
WORDSNET-16336 Khmer Mondulkiri font renders incorrectly Bug
WORDSNET-17887 Arial Font is used instead of Calibri Fonts during DOCM to PDF conversion Bug
WORDSNET-16703 TestRadialGradient is rendered improperly. Bug
WORDSNET-11650 System.NullReferenceException is thrown while saving DOCX to PDF Bug
WORDSNET-19294 TestLoadPerformanceLarge() performance test fails Bug
WORDSNET-16717 Background in MHT looks differently Bug

Public API and Backward Incompatible Changes

This section lists public API changes that were introduced in Aspose.Words 21.1. It includes not only new and obsoleted public methods, but also a description of any changes in the behavior behind the scenes in Aspose.Words which may affect existing code. Any behavior introduced that could be seen as regression and modifies the existing behavior is especially important and is documented here.

Added a new public property HtmlLoadOptions.IgnoreNoscriptElements

Related issue: WORDSNET-21203

Added a new public property HtmlLoadOptions.IgnoreNoscriptElements:

/// <summary>
/// Gets or sets a value indicating whether to ignore &lt;noscript&gt; HTML elements.
/// Default value is <c>false</c>.
/// </summary>
/// <remarks>
/// Like MS Word, Aspose.Words does not support scripts and by default loads content of &lt;noscript&gt; elements
/// into the resulting document. In most browsers, however, scripts are supported and content from &lt;noscript&gt;
/// is not visible. Setting this property to <c>true</c> forces Aspose.Words to ignore all &lt;noscript&gt; elements
/// and helps to produce documents that look closer to what is seen in browsers.
/// </remarks>
public bool IgnoreNoscriptElements { get; set; }

Customers may now instruct Aspose.Words to ignore <noscript> HTML elements like most modern browsers do.

Use Case:

HtmlLoadOptions loadOptions = new HtmlLoadOptions();
loadOptions.IgnoreNoscriptElements = true;

Added a new public property Node.CustomNodeId

Related issue: WORDSNET-21203

Added a new public property Node.CustomNodeId:

/// <summary>
/// Specifies custom node identifier.
/// </summary>
/// <remarks>
/// <p>Default is zero.</p>
/// <p>This identifier can be set and used arbitrarily. For example, as a key to get external data.</p>
/// </remarks>
public int CustomNodeId { get; set; }

Customers now may track node position in the model tree and bind external data based on assigned identifier:

Use Case:

DocumentBuilder builder = new DocumentBuilder();
Shape shape = builder.InsertShape(ShapeType.Rectangle, 100, 100);
shape.CustomNodeId = 100;

Added a new public property TableStyle.VerticalAlignment

Related issue: WORDSNET-21114

Added a new public options that allows to set table style cell vertical alignment.

/// <summary>
/// Specifies the vertical alignment for the cells.
/// </summary>
/// <remarks>
/// The default value is <see cref="CellVerticalAlignment.Top"/>.
/// </remarks>
public CellVerticalAlignment VerticalAlignment { get; set; }

Use Case:

Document doc = TestUtil.Open(fileName);
TableStyle style = (TableStyle)doc.Styles\["Custom Table 1"\];
style.VerticalAlignment = CellVerticalAlignment.Center;

Added new public methods StartColumnBookmark and EndColumnBookmark to DocumentBuilder class

Related issue: WORDSNET-18882

The following public methods have been added to the DocumentBuilder class:

/// <summary>
/// Marks the current position in the document as a column bookmark start. The position must be in a table cell.
/// </summary>
/// <remarks>
/// <p>A column bookmark covers one or more columns in a range of rows. To create a valid bookmark you
/// need to call both <see cref="StartColumnBookmark"/> and <see cref="EndColumnBookmark"/> with the same
/// <b>bookmarkName</b> parameter.</p>
/// <p>Badly formed bookmarks or bookmarks with duplicate names will be ignored when the document is saved.</p>
/// <p>The actual position of the inserted <see cref="BookmarkStart"/> node may differ from the current document
/// builder position.</p>
/// </remarks>
/// <param name="bookmarkName">Name of the bookmark.</param>
/// <returns>The bookmark start node that was just created.</returns>
public BookmarkStart StartColumnBookmark(string bookmarkName)
 
/// <summary>
/// Marks the current position in the document as a column bookmark end. The position must be in a table cell.
/// </summary>
/// <remarks>
/// <p>A column bookmark covers one or more columns in a range of rows. To create a valid bookmark you
/// need to call both <see cref="StartColumnBookmark"/> and <see cref="EndColumnBookmark"/> with the same
/// <b>bookmarkName</b> parameter.</p>
/// <p>Badly formed bookmarks or bookmarks with duplicate names will be ignored when the document is saved.</p>
/// <p>The actual position of the inserted <see cref="BookmarkEnd"/> node may differ from the current document
/// builder position.</p>
/// </remarks>
/// <param name="bookmarkName">Name of the bookmark.</param>
/// <returns>The bookmark end node that was just created.</returns>
public BookmarkEnd EndColumnBookmark(string bookmarkName)

Use Case:

Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
 
builder.StartTable();
 
builder.InsertCell();
builder.StartColumnBookmark("Bookmark1");
builder.Write("Cell 1");
 
builder.InsertCell();
builder.Write("Cell 2");
 
builder.InsertCell();
builder.Write("Cell 3");
 
builder.EndRow();
 
builder.InsertCell();
builder.Write("Cell 4");
 
builder.InsertCell();
builder.Write("Cell 5");
builder.EndColumnBookmark("Bookmark1");
 
builder.InsertCell();
builder.Write("Cell 6");
 
builder.EndRow();
builder.EndTable();
 
doc.Save(dir + "out.docx");

MarkdownSaveOptions.ImageSavingCallback has been added to control how images are saved upon converting to Markdown format

Related issue: WORDSNET-21389

A new public property ‘ImageSavingCallback’ has been added to the ‘MarkdownSaveOptions’ class:

/// <summary>
/// Allows to control how images are saved when a document is saved to <see cref="SaveFormat.Markdown"/> format.
/// </summary>
public IImageSavingCallback ImageSavingCallback

Use Case: Explains how to use ‘MarkdownSaveOptions.ImageSavingCallback’ when saving a document to markdown format

public void HandleDocument()
{
    const string outFileName = "SavingCallback.DocumentParts.Rendering.md";
 
    // Open a document to be converted to Markdown.
    Document doc = new Document("C:\\Rendering.docx");
 
    // We can use an appropriate SaveOptions subclass to customize the conversion process.
    MarkdownSaveOptions options = new MarkdownSaveOptions();
 
    // If we convert a document that contains images into Markdown, we will end up with one Markdown file which links to several images.
    // Each image will be in the form of a file in the local file system.
    // There is also a callback that can customize the name and file system location of each image.
    options.ImageSavingCallback = new SavedImageRename(outFileName);
 
    // The ImageSaving() method of our callback will be run at this time.
    doc.Save($"C:\\{outFileName}", options);
}

/// <summary>
/// Renames saved images that are produced when an Markdown document is saved.
/// </summary>
public class SavedImageRename : IImageSavingCallback
{
    public SavedImageRename(string outFileName)
    {
        mOutFileName = outFileName;
    }
 
    void IImageSavingCallback.ImageSaving(ImageSavingArgs args)
    {
        string imageFileName = $"{mOutFileName} shape {++mCount}, of type {args.CurrentShape.ShapeType}{Path.GetExtension(args.ImageFileName)}";
 
        args.ImageFileName = imageFileName;
        args.ImageStream = new FileStream($"C:\\{imageFileName}", FileMode.Create);
 
        Assert.True(args.ImageStream.CanWrite);
        Assert.True(args.IsImageAvailable);
        Assert.False(args.KeepImageStreamOpen);
    }
 
    private int mCount;
    private readonly string mOutFileName;
}

PdfSaveOptions.EscapeUri is marked as obsolete

We made several improvements in export of hyperlinks to PDF per WORDSNET-21443. Now the cases when setting PdfSaveOptions.EscapeUri to false was required (improper unescaping of explicitly escaped URI delimiter chars) are handled well by default. Thus we do not see a reason to keep this option longer and marked it as obsolete.

/// <summary>
/// A flag specifying whether URI should be escaped before writing.
/// </summary>
/// <remarks>
/// Note that if this option is set to <c>false</c> hyperlinks are written "as is",
/// so valid (escaped) URI should be provided in document's model.
/// <para>The default value is <c>true</c>.</para>
/// </remarks>
[Obsolete("Writing of URI to PDF was improved and cases when disabled escaping was required are handled well now.")]
public bool EscapeUri { get; set; }

Removed obsolete properties FixedPageSaveOptions.PageIndex, FixedPageSaveOptions.PageCount, ImageSaveOptions.PageIndex, ImageSaveOptions.PageCount

Related issue: WORDSNET-21154

Deprecated properties related to page specification when printing were removed from the FixedPageSaveOptions and ImageSaveOptions classes.

[Obsolete("This property is obsolete. Please use PageSet property instead.")]
public new int PageCount
[Obsolete("This property is obsolete. Please use PageSet property instead.")]
public new int PageIndex

The behavior of DocumentBuilder.InsertOleObject() and DocumentBuilder.InsertOleObjectAsIcon() methods was changed

Related issue: WORDSNET-21426

In cases where the DocumentBuilder.InsertOleObject() and DocumentBuilder.InsertOleObjectAsIcon() methods need to create an icon with a caption, they can use the file extension to define the icon, and can use the filename for the icon caption.

More details:

public Shape InsertOleObject(Stream stream, string progId, bool asIcon, Stream presentation)
If ‘presentation’ is omitted and ‘asIcon’ is set, this overloaded method selects the icon according to ‘progId’ and uses the predefined icon caption.

public Shape InsertOleObject(string fileName, bool isLinked, bool asIcon, Stream presentation)
If ‘presentation’ is omitted and ‘asIcon’ is set, this overloaded method selects the icon according to the file extension and uses the filename for the icon caption.

public Shape InsertOleObject(string fileName, string progId, bool isLinked, bool asIcon, Stream presentation)
If ‘presentation’ is omitted and ‘asIcon’ is set, this overloaded method selects the icon according to ‘progId’ and uses the filename for the icon caption.

public Shape InsertOleObjectAsIcon(Stream stream, string progId, string iconFile, string iconCaption)
If ‘iconFile’ and ‘iconCaption’ are omitted, this overloaded method selects the icon according to ‘progId’ and uses the predefined icon caption.

public Shape InsertOleObjectAsIcon(string fileName, string progId, bool isLinked, string iconFile, string iconCaption)
If ‘iconFile’ and ‘iconCaption’ are omitted, this overloaded method selects the icon according to ‘progId’ and uses the filename for the icon caption.

public Shape InsertOleObjectAsIcon(string fileName, bool isLinked, string iconFile, string iconCaption)
If ‘iconFile’ and ‘iconCaption’ are omitted, this overloaded method selects the icon according to the file extension and uses the filename for the icon caption.

Changed XML comments for ‘iconCaption’ arguments of DocumentBuilder.InsertOleObjectAsIcon() methods:

/// <summary>
/// Inserts an embedded or linked OLE object as icon into the document.
/// Allows to specify icon file and caption. Detects OLE object type using file extension.
/// </summary>
/// <param name="fileName">Full path to the file.</param>
/// <param name="isLinked">
/// If true then linked OLE object is inserted otherwise embedded OLE object is inserted.
/// </param>
/// <param name="iconFile">
/// Full path to the ICO file. If the value is null, Aspose.Words will use a predefined image.
/// </param>
/// <param name="iconCaption">
/// Icon caption. If the value is null, Aspose.Words will use the file name.
/// </param>
/// <returns>Shape node containing Ole object and inserted at the current Builder position.</returns>
public Shape InsertOleObjectAsIcon(string fileName, bool isLinked, string iconFile, string iconCaption)

/// <summary>
/// Inserts an embedded or linked OLE object as icon into the document.
/// Allows to specify icon file and caption. Detects OLE object type using given progID parameter.
/// </summary>
/// <param name="fileName">Full path to the file.</param>
/// <param name="progId">ProgId of OLE object.</param>
/// <param name="isLinked">
/// If true then linked OLE object is inserted otherwise embedded OLE object is inserted.
/// </param>
/// <param name="iconFile">
/// Full path to the ICO file. If the value is null, Aspose.Words will use a predefined image.
/// </param>
/// <param name="iconCaption">
/// Icon caption. If the value is null, Aspose.Words will use the file name.
/// </param>
/// <returns>Shape node containing Ole object and inserted at the current Builder position.</returns>

public Shape InsertOleObjectAsIcon(string fileName, string progId, bool isLinked, string iconFile, string iconCaption)
/// <summary>
/// Inserts an embedded OLE object as icon from a stream into the document.
/// Allows to specify icon file and caption. Detects OLE object type using given progID parameter.
/// </summary>
/// <param name="stream">Stream containing application data.</param>
/// <param name="progId">ProgId of OLE object.</param>
/// <param name="iconFile">
/// Full path to the ICO file. If the value is null, Aspose.Words will use a predefined image.
/// </param>
/// <param name="iconCaption">
/// Icon caption. If the value is null, Aspose.Words will use the a predefined icon caption.
/// </param>
/// <returns>Shape node containing Ole object and inserted at the current Builder position.</returns>
public Shape InsertOleObjectAsIcon(Stream stream, string progId, string iconFile, string iconCaption)

The behavior of revision tracking feature triggered by Document.StartTrackRevisions was changed

Related issue: WORDSNET-20666

When revisions are tracked using Document.StartTrackRevisions, if a node is moved from one location to another in the same document, move revisions are now generated, including move-from and move-to ranges.

Use Case:

Document doc = new Document();
DocumentBuilder builder = new DocumentBuilder(doc);
 
// Generate document contents.
builder.Writeln("Paragraph 1");
builder.Writeln("Paragraph 2");
builder.Writeln("Paragraph 3");
builder.Writeln("Paragraph 4");
builder.Writeln("Paragraph 5");
builder.Writeln("Paragraph 6");
 
Body body = doc.FirstSection.Body;
 
// Returns 7.
Console.WriteLine("Paragraph count: {0}", body.Paragraphs.Count);
 
doc.StartTrackRevisions("Author", new DateTime(2020, 12, 23, 14, 0, 0));
 
Node node = body.Paragraphs[3];
Node endNode = body.Paragraphs[5].NextSibling;
Node referenceNode = body.Paragraphs[0];
 
while (node != endNode)
{
    Node nextNode = node.NextSibling;
    body.InsertBefore(node, referenceNode);
    node = nextNode;
}
 
doc.StopTrackRevisions();
 
// Returns 10: there are 3 additional paragraphs in the move-from range.
Console.WriteLine("Paragraph count: {0}", body.Paragraphs.Count);
 
doc.Save(dir + @"out.docx");