GroupDocs.Merger for .NET 26.9 Release Notes

There are 14 features, improvements, and bug fixes in this release.

This release adds row-wise joining of spreadsheets into a single sheet and makes PageBuilder apply the page selection of the first TIFF document. It fixes concurrency issues with Visio documents and with PDF and XPS documents joined into DOC, honours the requested preview size in every document format family, and replaces several silent outcomes — a missing license file, an empty page list, an unsupported image or audio join — with clear exceptions.

Full list of changes in this release

KeyCategorySummary
MERGERNET-2198FeatureMerge Excel rows from multiple files into a single sheet
MERGERNET-1372FeatureApply the PageBuilder page selection to the first TIFF document
MERGERNET-2183ImprovementThrow an exception when SetLicense cannot find the license file
MERGERNET-2184ImprovementReject an empty license stream in SetLicense
MERGERNET-2190ImprovementThrow a clear exception when joining an image or audio file into an unsupported format
MERGERNET-2202ImprovementDrop System.Drawing.Common from the cross-platform packages and report missing dependencies clearly
MERGERNET-2187BugClose the source file after Merger opens or joins a document by path
MERGERNET-2189BugCall the stream factory only once when constructing Merger
MERGERNET-2192BugFix corrupt DOC output when joining PDF or XPS documents into DOC from multiple threads
MERGERNET-2194BugApply a page orientation change to every page when no page numbers are specified
MERGERNET-2196BugHonour the requested preview Width and Height in every document format family
MERGERNET-2197BugReject ExtractPages and RemovePages called with no page numbers instead of silently producing an empty or unchanged document
MERGERNET-2199BugFix Visio documents intermittently failing with ArgumentNullException trueTypeFont when processed concurrently
MERGERNET-2200BugFix PDF portfolios failing with NullReferenceException when an embedded file has no modification date

Major Features

  • Row-wise spreadsheet joining: Rows of several spreadsheets can now be appended into a single sheet of the result instead of being added as separate worksheets, with an option to skip header rows of the appended files and to match sheets by position.

  • PageBuilder for TIFF documents: A page selection made with PageBuilder is now applied to the first TIFF document as well — previously all of its pages were always included. Joins that do not use PageBuilder are unchanged.

  • Accurate preview dimensions: GeneratePreview now returns images at the requested Width and Height for every document format family, including Word processing, spreadsheet, Visio and OneNote documents. When only one dimension is given, the other is derived from the page’s aspect ratio.

  • Concurrency fixes: Visio documents no longer fail intermittently when processed from several threads, and PDF and XPS documents joined into DOC from several threads no longer produce corrupt output.

  • Resource handling: A document opened or joined by file path no longer keeps the source file open after its content has been read, and a Merger constructed from a stream factory calls that factory exactly once.

  • Clearer errors: Joining an image or audio file into an unsupported target format, calling ExtractPages or RemovePages without page numbers, and calling SetLicense with a missing license file or an empty license stream now throw an exception instead of failing silently. A missing runtime dependency is reported as MissingDependencyException, naming the assembly and how to install it. PDF portfolios whose embedded files have no modification date now open normally.

Public API and backward incompatible changes

1. Spreadsheet joining — row-wise mode (new API)

New public types in the GroupDocs.Merger.Domain.Options namespace:

TypeDescription
SpreadsheetJoinOptionsJoin options for spreadsheets, derived from PageJoinOptions. Properties: Mode, SkipRows, SheetMatching.
SpreadsheetJoinModeWorksheets (default) adds the sheets of the joined file as separate worksheets, as before. Rows appends the rows of each joined file below the last row containing data of the matching sheet of the result.
SpreadsheetSheetMatchingByIndex (default) appends sheet 2 to sheet 2, sheet 3 to sheet 3, and so on; worksheets beyond the number of result worksheets are added as new worksheets. FirstSheetOnly appends only the first sheet of each joined file.
  • SkipRows skips the first N rows of every joined file, for example a header row. The first document — the one the Merger was created with — is always taken in full. SkipRows and SheetMatching have no effect in Worksheets mode.
  • Supported formats: XLSX, XLS, XLSM, XLSB, XLTX, XLTM, XLT, XLAM and ODS. Row-wise mode also works when the joined spreadsheet has a different format than the main document (for example, XLS joined into XLSX).
  • Carried over: cell values, formulas (relative references are adjusted to the new position), cell styles, merged cells and row heights. Not carried over: charts, pictures and other floating objects, pivot tables, tables, conditional formatting and data validation of the joined files.
  • A negative SkipRows throws GroupDocsMergerException (“The count of rows to skip can not be negative.”), in any mode.
  • Appending more rows than the output format allows (65,536 for XLS and XLT, 1,048,576 for the other formats) throws GroupDocsMergerException.
  • ApplyPageBuilder throws GroupDocsMergerException while a spreadsheet joined in Rows mode is pending, because appended rows do not form separate pages.
  • Joins without SpreadsheetJoinOptions, or with the default Mode, behave exactly as before.
using GroupDocs.Merger;
using GroupDocs.Merger.Domain.Options;

using (var merger = new Merger("january.xlsx"))
{
    var options = new SpreadsheetJoinOptions
    {
        Mode = SpreadsheetJoinMode.Rows,   // append rows into the existing sheets
        SkipRows = 1                        // skip the header row of each joined file
    };

    merger.Join("february.xlsx", options);
    merger.Join("march.xlsx", options);
    merger.Save("q1.xlsx");
}

2. TIFF — PageBuilder applies the first document’s page selection

No API change. CreatePageBuilder and ApplyPageBuilder now apply the pages selected from the first TIFF document; previously all pages of the first document were always included and only the selection of the joined documents was applied. Joins that do not use PageBuilder produce the same result as before.

After a join with ImageJoinOptions, CreatePageBuilder and ApplyPageBuilder now throw GroupDocsMergerException, because joined images are composed into one layout rather than a page sequence; previously the page builder contained no documents and AddPage failed with “Invalid document index”. To compose TIFF files page by page, join them without ImageJoinOptions.

using GroupDocs.Merger;
using GroupDocs.Merger.Domain.Builders;

using (var merger = new Merger("source1.tiff"))
{
    merger.Join("source2.tiff");

    PageBuilder builder = merger.CreatePageBuilder();

    // Document 0 = source1.tiff, Document 1 = source2.tiff
    builder.AddPage(0, 3);   // page 3 of source1.tiff
    builder.AddPage(1, 2);   // page 2 of source2.tiff
    builder.AddPage(0, 1);   // page 1 of source1.tiff

    merger.ApplyPageBuilder(builder);
    merger.Save("merged.tiff");   // exactly these three pages, in this order
}

3. Licensing — SetLicense no longer fails silently

  • License.SetLicense(string licensePath) throws InvalidOperationException (“License not found: …”) when the license file cannot be found. Previously the call returned without applying a license, and the product continued in evaluation mode. A null or empty path throws ArgumentException.
  • License.SetLicense(Stream licenseStream) throws ArgumentNullException for an empty stream, as it already did for a null stream.

4. Page operations with an empty page list

  • ExtractPages and RemovePages called with no page numbers now throw GroupDocsMergerException (“There are no page numbers to extract.” / “There are no page numbers to remove.”). Previously ExtractPages could produce an empty document and RemovePages returned the document unchanged.
  • ChangeOrientation called with no page numbers now changes the orientation of every page for PDF, XPS, Word processing, spreadsheet and Visio documents. Previously no page was changed.

5. Preview size

GeneratePreview now resizes every page image to the requested Width and Height — stretched to exactly that size when both are given. Previews of Word processing, spreadsheet, Visio and OneNote documents, and previews requested with only one dimension, can therefore differ in size from previous versions. A negative Width or Height now throws GroupDocsMergerException instead of being ignored.


6. System.Drawing.Common and missing dependencies

  • The cross-platform packages GroupDocs.Merger.Net60, GroupDocs.Merger.Net80 and GroupDocs.Merger.Net100 no longer depend on System.Drawing.Common. The .Windows and .Net462 packages still include it. An application that used System.Drawing.Common through GroupDocs.Merger must now reference that package itself.
  • When a required assembly or native library is missing at run time, operations throw the new MissingDependencyException (GroupDocs.Merger.Exceptions, derived from GroupDocsMergerException). Its message names the missing component and how to install it, and its AssemblyName property returns the name of the assembly that could not be loaded, when it can be determined. Processing OneNote and SVG documents on the cross-platform packages requires System.Drawing.Common.

7. Joining images and audio into unsupported formats

Joining an image or audio file into a document format it cannot be joined into (for example, PNG into DOCX, or WAV into MP3) now throws FileTypeNotSupportedException (“Joining ‘…’ into ‘…’ is not supported”). Previously the join produced an empty result for that file.