Browse our Products

Aspose.Words for C++ 21.1 Release Notes

Major Features

We have added the following features from Aspose.Words for .NET on this regular monthly release:

  • 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.

Limitations and API Differences

Aspose.Words for C++ has some differences as compared to its equivalent .NET version of the API. This section contains information about all such functionality that is not available in the current release. The missing features will be added in future releases.

  • The current release does not support Metered license.
  • The current release does not support LINQ and Reporting features.
  • The current release does not support OpenGL 3D Shapes rendering.
  • The current release does not support advanced typography based on HarfBuzz shaper.
  • The current release does not support loading PDF documents.
  • The current release has limited support for database features - C++ doesn’t have common API for DB like .NET System.Data.
  • The current release supports Microsoft Visual C++ version 2017 or higher.
  • The current release supports GCC 6.3 or higher and Clang 3.9.1 or higher on Linux and only for the x86_x64 platform.

Full List of Issues Covering all Changes in this Release

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

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 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>
bool get_IgnoreNoscriptElements() const;

/// Setter for HtmlLoadOptions::IgnoreNoscriptElements
void set_IgnoreNoscriptElements(bool value);

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

Use Case:

auto loadOptions = MakeObject<HtmlLoadOptions>();
loadOptions->set_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>
void int32_t get_CustomNodeId() const;
void void set_CustomNodeId(int32_t value);

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

Use Case:

auto doc = MakeObject<Document>();
auto builder = MakeObject<DocumentBuilder>(doc);
auto shape = builder->InsertShape(ShapeType::Rectangle, 100, 100);
shape->set_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>
CellVerticalAlignment get_VerticalAlignment() const;
void set_VerticalAlignment(CellVerticalAlignment value);

Use Case:

auto doc = MakeObject<Document>(filename);
auto style = StaticCast<TableStyle>(doc->get_Styles()->idx_get(u"Custom Table 1"));
style->set_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>
SharedPtr<BookmarkStart> StartColumnBookmark(System::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>
SharedPtr<BookmarkEnd> EndColumnBookmark(System::String bookmarkName);

Use Case:

auto doc = MakeObject<Document>();
auto builder = MakeObject<DocumentBuilder>(doc);
 
builder->StartTable();
 
builder->InsertCell();
builder->StartColumnBookmark(u"Bookmark1");
builder->Write(u"Cell 1");
 
builder->InsertCell();
builder->Write(u"Cell 2");
 
builder->InsertCell();
builder->Write(u"Cell 3");
 
builder->EndRow();
 
builder->InsertCell();
builder->Write(u"Cell 4");
 
builder->InsertCell();
builder->Write(u"Cell 5");
builder->EndColumnBookmark(u"Bookmark1");
 
builder->InsertCell();
builder->Write(u"Cell 6");
 
builder->EndRow();
builder->EndTable();
 
doc->Save(u"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>
SharedPtr<IImageSavingCallback> get_ImageSavingCallback() const;
void set_ImageSavingCallback(SharedPtr<IImageSavingCallback> value);

Use Case:

class SavedImageRename;

void HandleDocument()
{
    String outFileName = u"SavingCallback.DocumentParts.Rendering.md";
 
    // Open a document to be converted to Markdown.
    auto doc = MakeObject<Document>("Rendering.docx");
 
    // We can use an appropriate SaveOptions subclass to customize the conversion process.
    auto options = MakeObject<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->set_ImageSavingCallback(MakeObject<SavedImageRename>(outFileName));
 
    // The ImageSaving() method of our callback will be run at this time.
    doc->Save(outFileName, options);
}

/// <summary>
/// Renames saved images that are produced when an Markdown document is saved.
/// </summary>
class SavedImageRename : public IImageSavingCallback
{
public:
    SavedImageRename(String outFileName) : mOutFileName(outFileName) {}
 
    void ImageSaving(SharedPtr<ImageSavingArgs> args) override
    {
        mCount++;
        String imageFileName = String::Format(u"{0} shape {1}, of type {2}{3}",
          mOutFileName, mCount, ObjectExt::ToString(args->get_CurrentShape()->get_ShapeType()),
          Path::GetExtension(args->get_ImageFileName());
 
        args->set_ImageFileName(imageFileName);
        args->set_ImageStream(MakeObject<FileStream>(imageFileName, FileMode::Create));
    }
 
private:
    int32_t mCount = 0;
    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>
[[deprecated("Writing of URI to PDF was improved and cases when disabled escaping was required are handled well now.")]]
bool get_EscapeUri() const;

[[deprecated("Writing of URI to PDF was improved and cases when disabled escaping was required are handled well now.")]]
void set_EscapeUri(bool value);

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.

[[deprecated("This property is obsolete. Please use PageSet property instead.")]]
int32_t get_PageCount() const;
[[deprecated("This property is obsolete. Please use PageSet property instead.")]]
void set_PageCount(int32_t value);

[[deprecated("This property is obsolete. Please use PageSet property instead.")]]
int32_t get_PageIndex() const;
[[deprecated("This property is obsolete. Please use PageSet property instead.")]]
void set_PageIndex(int32_t value);

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:

SharedPtr<Shape> InsertOleObject(SharedPtr<Stream> stream, String progId, bool asIcon, SharedPtr<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.

SharedPtr<Shape> InsertOleObject(String fileName, bool isLinked, bool asIcon, SharedPtr<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.

SharedPtr<Shape> InsertOleObject(String fileName, String progId, bool isLinked, bool asIcon, SharedPtr<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.

SharedPtr<Shape> InsertOleObjectAsIcon(SharedPtr<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.

SharedPtr<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.

SharedPtr<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>
SharedPtr<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>
SharedPtr<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>
SharedPtr<Shape> InsertOleObjectAsIcon(SharedPtr<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:

auto doc = MakeObject<Document>();
auto builder = MakeObject<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");
 
auto body = doc->get_FirstSection()->get_Body();
 
// Returns 7.
std::cout << "Paragraph count: " << body->get_Paragraphs()->get_Count() << '\n';
 
doc->StartTrackRevisions(u"Author", DateTime(2020, 12, 23, 14, 0, 0));
 
auto node = body->get_Paragraphs()->idx_get(3);
auto endNode = body->get_Paragraphs()->idx_get(5)->get_NextSibling();
auto referenceNode = body->get_Paragraphs()->idx_get(0);
 
while (node != endNode)
{
    auto nextNode = node->get_NextSibling();
    body->InsertBefore(node, referenceNode);
    node = nextNode;
}
 
doc->StopTrackRevisions();
 
// Returns 10: there are 3 additional paragraphs in the move-from range.
std::cout << "Paragraph count: " << body->get_Paragraphs()->get_Count() << '\n';
 
doc->Save("out.docx");