Skip to main content Skip to footer

What's New in Document Solutions for Excel v9.1

We’re excited to introduce Document Solutions for Excel (DsExcel) v9.1, a release that expands support for modern Excel features, improves export fidelity, and strengthens interoperability with SpreadJS. This update adds support for cell checkboxes, picture-in-cell, pivot table enhancements, better printing control, and richer PDF export for charts and bullets, while the Document Solutions Data Viewer (DsDataViewer) adds interactive PivotTable support for a more dynamic browser-based analysis experience.

DsExcel v9.1 also improves the template engine with more powerful filtering and better SpreadJS template expansion, while adding several lossless I/O enhancements for newer SpreadJS workbook features, increasing compatibility. Together, these updates make it easier to build interactive spreadsheet solutions, generate higher-fidelity exports, and preserve more workbook behavior across Excel, JSON, and SpreadJS workflows. To read about the latest v9.1 features in our other Document Solutions products, check out the accompanying What’s New blog here.

Document Solutions for Excel v9.1 Includes

Download the Latest Release of the .NET or Java Excel APIs Today!


New Features Support in DsExcel v9.1

Support for Cell Checkboxes

DsExcel v9.1 adds support for cell checkboxes, a more flexible alternative to traditional form controls for interactive lists and forms. Because the checkbox is part of the cell, it moves naturally with sorting, filtering, and row operations, making it much easier to build Excel-like checklist experiences.

Developers can work with checkboxes through IRange.CellControl, using methods such as SetCheckbox() and RemoveControls(), while the checked state is driven by the cell value itself. true, false, and null map to checked, unchecked, and indeterminate states, respectively. Cell checkboxes are also supported in PDF and image export, and they round-trip through SJS, SSJSON, and XLSX.

Programmatically Add Checkboxes to Generated Excel Files - Developer SDK

C#:

Workbook workbook = new Workbook();
workbook.ActiveSheet.Range["A1:C2"].CellControl.SetCheckbox();
workbook.ActiveSheet.Range["A1:C2"].Value = false;

Console.WriteLine(workbook.ActiveSheet.Range["A1:C2"].CellControl.Type);

Java:

IWorkbook workbook = new Workbook();

workbook.getActiveSheet().getRange("A1:C2").getCellControl().setCheckbox();
workbook.getActiveSheet().getRange("A1:C2").setValue(false);
        
System.out.println(workbook.getActiveSheet().getRange("A1:C2").getCellControl().getType());

Help .NET | Demo .NET | Help Java | Demo Java

Support for Waterfall Chart Export

DsExcel v9.1 adds support for Waterfall chart export to PDF, with support extending to image and HTML output as well. This helps developers preserve one of Excel’s most useful financial and variance-analysis chart types when generating reports outside Excel.

Subtotal and total points can be defined using the existing chart object model, and connector lines can be shown or hidden to match the intended chart design. With this improvement, Waterfall charts render much more faithfully in exported output without requiring any new API surface.

.NET and Java Excel APIs Support for Waterfall Charts Export to PDF

C#:

//create a new workbook
var workbook = new GrapeCity.Documents.Excel.Workbook();
IWorksheet worksheet = workbook.Worksheets[0];
worksheet.Range["A1:B8"].Value = new object[,]
{
    {"Starting Amt", 130},
    {"Measurement 1", 25},
    {"Measurement 2", -75},
    {"Subtotal", 80},
    {"Measurement 3", 45},
    {"Measurement 4", -65},
    {"Measurement 5", 80},
    {"Total", 140}
};
worksheet.Range["A:A"].Columns.AutoFit();

// Create a waterfall chart.
IShape shape = worksheet.Shapes.AddChart(ChartType.Waterfall, worksheet.Range["A9:H26"]);
shape.Chart.SeriesCollection.Add(worksheet.Range["A1:B8"]);

// Set subtotal&total points.
IPoints points = shape.Chart.SeriesCollection[0].Points;
points[3].IsTotal = true;
points[7].IsTotal = true;

// Connector lines are not shown.
ISeries series = shape.Chart.SeriesCollection[0];
series.ShowConnectorLines = true;

workbook.Save("WaterfallChart.pdf");

Java:

// Create a new workbook
Workbook workbook = new Workbook();
IWorksheet worksheet = workbook.getWorksheets().get(0);

worksheet.getRange("A1:B8").setValue(new Object[][]{
        {"Starting Amt", 130},
        {"Measurement 1", 25},
        {"Measurement 2", -75},
        {"Subtotal", 80},
        {"Measurement 3", 45},
        {"Measurement 4", -65},
        {"Measurement 5", 80},
        {"Total", 140}
});

worksheet.getRange("A:A").getColumns().autoFit();

// Create a waterfall chart.
IShape shape = worksheet.getShapes()
        .addChart(ChartType.Waterfall, worksheet.getRange("A9:H26"));

shape.getChart().getSeriesCollection()
        .add(worksheet.getRange("A1:B8"));

// Set subtotal & total points.
IPoints points = shape.getChart()
        .getSeriesCollection().get(0)
        .getPoints();

points.get(3).setIsTotal(true);
points.get(7).setIsTotal(true);

// Show connector lines.
ISeries series = shape.getChart().getSeriesCollection().get(0);
series.setShowConnectorLines(true);

// Modify the fill color of the first legend entry.
ILegendEntries legendEntries =
        shape.getChart().getLegend().getLegendEntries();

legendEntries.get(0)
        .getFormat().getFill().getColor()
        .setObjectThemeColor(ThemeColor.Accent6);
    
// Save to a pdf file
workbook.save("WaterfallChartPdf.pdf");

Help .NET | Demo .NET | Help Java | Demo Java

Support for Exporting Bullets to PDF

DsExcel v9.1 improves PDF fidelity by adding support for bullets in shape text, so bullet formatting is no longer lost when exporting workbooks to PDF. This is especially useful for text boxes and other shape-based content that rely on bulleted lists for layout and readability.

The export engine now preserves bullet type, color, and size for symbol bullets, automatic numbering bullets, and custom bullets, helping PDF output more closely match Excel. Image-based bullets are not yet supported, but standard bullet formatting now renders much more accurately.

Support for Export Excel Bullets to PDF using .NET or Java

C#:

// Create a new workbook
var workbook = new Workbook();
// Open an excel file
workbook.Open("IncludesBullet.xlsx"); // The Excel file contains Shape ->Textbox ->Bullet.
// Save to a pdf file
workbook.Save("res.pdf");

Java:

// Create a new workbook
Workbook workbook = new Workbook();
// Open an excel file
InputStream fileStream = this.getResourceStream("xlsx/ShapeWithBullet.xlsx");
workbook.open(fileStream);
// Save to a pdf file
workbook.save("ShapeWithBullet.pdf");

Help .NET | Demo .NET | Help Java | Demo Java

Support for Pivot Table Dynamic Cell Styling

DsExcel v9.1 adds support for dynamic pivot table cell styling, improving compatibility with Excel’s pivot formatting behavior. Styles applied to cells within a pivot table are now preserved even after refreshes or layout changes, rather than being tied only to a fixed cell position.

This is especially useful when highlighting important row or column items in reports that may later be refreshed or reconfigured. The feature works through existing pivot table styling behavior and does not require a new public API.

Excel API Support for Pivot Tables Dynamic Cell Styling

C#

IWorkbook workbook = new Workbook();
IWorksheet worksheet = workbook.getActiveSheet();

// Set up source data
Object[][] sourceData = new Object[][]{
    {"Order ID", "Product", "Category", "Amount"},
    {1, "Carrots", "Vegetables", 4270},
    {2, "Broccoli", "Vegetables", 8239},
    {3, "Banana", "Fruit", 617},
    {4, "Apple", "Fruit", 8384}
};
worksheet.getRange("A1:D5").setValue(sourceData);

// Create pivot cache and pivot table
IPivotCache pivotCache = workbook.getPivotCaches().create(worksheet.getRange("A1:D5"));
IPivotTable pivotTable = worksheet.getPivotTables().add(pivotCache, worksheet.getRange("F1"));

// Set up pivot table structure
pivotTable.getPivotFields().get("Category").setOrientation(PivotFieldOrientation.ColumnField);
pivotTable.getPivotFields().get("Product").setOrientation(PivotFieldOrientation.RowField);
pivotTable.getPivotFields().get("Amount").setOrientation(PivotFieldOrientation.DataField);

// Apply dynamic style to a cell in the pivot table area
worksheet.getRange("F1").getInterior().setColor(Color.GetRed());

// Refresh pivot table - the style will be preserved
pivotTable.refresh();

// The style is still applied after refresh
System.out.println(worksheet.getRange("F1").getInterior().getColor()); // Output: Color.GetRed()

// Save to Excel - styles are preserved
workbook.save("PivotTableWithStyle.xlsx");

Support for Showing or Hiding Pivot Table Field Headers

DsExcel v9.1 adds support for showing or hiding PivotTable row and column field headers, making it easier to create cleaner reports and dashboard-style summaries. This behavior is controlled through the new IPivotTable.DisplayFieldCaptions property.

When field captions are hidden, DsExcel adjusts the pivot layout automatically, either removing header-only rows or hiding just the header cells where needed. This gives developers more control over final report presentation while keeping pivot table generation simple.

When IPivotTable.DisplayFieldCaptions = True:

IPivotTable.DisplayFieldCaptions = True Example

When IPivotTable.DisplayFieldCaptions = False:

IPivotTable.DisplayFieldCaptions = False Example

C#:

  object[,] sourceData = new object[,] {
      { "Order ID", "Product",               "Category",              "Amount", "Date",                    "Country" },
      { 1,          "Bose 785593-0050",      "Consumer Electronics",  4270,     new DateTime(2018, 1, 6),  "United States" },
      { 2,          "Canon EOS 1500D",       "Consumer Electronics",  8239,     new DateTime(2018, 1, 7),  "United Kingdom" },
      { 3,          "Haier 394L 4Star",      "Consumer Electronics",  617,      new DateTime(2018, 1, 8),  "United States" },
      { 4,          "IFB 6.5 Kg FullyAuto",  "Consumer Electronics",  8384,     new DateTime(2018, 1, 10), "Canada" },
      { 5,          "Mi LED 40inch",         "Consumer Electronics",  2626,     new DateTime(2018, 1, 10), "Germany" },
      { 6,          "Sennheiser HD 4.40-BT", "Consumer Electronics",  3610,     new DateTime(2018, 1, 11), "United States" },
      { 7,          "Iphone XR",             "Mobile",                9062,     new DateTime(2018, 1, 11), "Australia" },
      { 8,          "OnePlus 7Pro",          "Mobile",                6906,     new DateTime(2018, 1, 16), "New Zealand" },
      { 9,          "Redmi 7",               "Mobile",                2417,     new DateTime(2018, 1, 16), "France" },
      { 10,         "Samsung S9",            "Mobile",                7431,     new DateTime(2018, 1, 16), "Canada" },
      { 11,         "OnePlus 7Pro",          "Mobile",                8250,     new DateTime(2018, 1, 16), "Germany" },
      { 12,         "Redmi 7",               "Mobile",                7012,     new DateTime(2018, 1, 18), "United States" },
      { 13,         "Bose 785593-0050",      "Consumer Electronics",  1903,     new DateTime(2018, 1, 20), "Germany" },
      { 14,         "Canon EOS 1500D",       "Consumer Electronics",  2824,     new DateTime(2018, 1, 22), "Canada" },
      { 15,         "Haier 394L 4Star",      "Consumer Electronics",  6946,     new DateTime(2018, 1, 24), "France" },
  };
  
  // Create a workbook
  Workbook workbook = new Workbook();
  IWorksheet worksheet = workbook.Worksheets[0];
  worksheet.Range["M1:R16"].Value = sourceData;
  worksheet.Range["M:R"].ColumnWidth = 15;

  // Create pivot table with DisplayFieldCaptions = false
  var pivotcache1 = workbook.PivotCaches.Create(worksheet.Range["M1:R16"]);
  var pivottable1 = worksheet.PivotTables.Add(pivotcache1, worksheet.Range["A3"], "pivottable1");
  worksheet.Range["P1:P16"].NumberFormat = "$#,##0.00";

  // Config pivot table's fields
  var field_Category1 = pivottable1.PivotFields["Category"];
  field_Category1.Orientation = PivotFieldOrientation.ColumnField;

  var field_Product1 = pivottable1.PivotFields["Product"];
  field_Product1.Orientation = PivotFieldOrientation.RowField;

  var field_Amount1 = pivottable1.PivotFields["Amount"];
  field_Amount1.Orientation = PivotFieldOrientation.DataField;
  field_Amount1.NumberFormat = "$#,##0.00";

  // Set DisplayFieldCaptions to false
  pivottable1.DisplayFieldCaptions = false;
  
  worksheet.Range["A:K"].EntireColumn.AutoFit();
  workbook.Save("pivotTableWithoutFieldHeaders.xlsx");

Java:

  Object sourceData = new Object[][]{
          {"Order ID", "Product", "Category", "Amount", "Date", "Country"},
          {1, "Bose 785593-0050", "Consumer Electronics", 4270, new GregorianCalendar(2018, 0, 6), "United States"},
          {2, "Canon EOS 1500D", "Consumer Electronics", 8239, new GregorianCalendar(2018, 0, 7), "United Kingdom"},
          {3, "Haier 394L 4Star", "Consumer Electronics", 617, new GregorianCalendar(2018, 0, 8), "United States"},
          {4, "IFB 6.5 Kg FullyAuto", "Consumer Electronics", 8384, new GregorianCalendar(2018, 0, 10), "Canada"},
          {5, "Mi LED 40inch", "Consumer Electronics", 2626, new GregorianCalendar(2018, 0, 10), "Germany"},
          {6, "Sennheiser HD 4.40-BT", "Consumer Electronics", 3610, new GregorianCalendar(2018, 0, 11), "United States"},
          {7, "Iphone XR", "Mobile", 9062, new GregorianCalendar(2018, 0, 11), "Australia"},
          {8, "OnePlus 7Pro", "Mobile", 6906, new GregorianCalendar(2018, 0, 16), "New Zealand"},
          {9, "Redmi 7", "Mobile", 2417, new GregorianCalendar(2018, 0, 16), "France"},
          {10, "Samsung S9", "Mobile", 7431, new GregorianCalendar(2018, 0, 16), "Canada"},
          {11, "OnePlus 7Pro", "Mobile", 8250, new GregorianCalendar(2018, 0, 16), "Germany"},
          {12, "Redmi 7", "Mobile", 7012, new GregorianCalendar(2018, 0, 18), "United States"},
          {13, "Bose 785593-0050", "Consumer Electronics", 1903, new GregorianCalendar(2018, 0, 20), "Germany"},
          {14, "Canon EOS 1500D", "Consumer Electronics", 2824, new GregorianCalendar(2018, 0, 22), "Canada"},
          {15, "Haier 394L 4Star", "Consumer Electronics", 6946, new GregorianCalendar(2018, 0, 24), "France"},
  };
  
  // Create a workbook
  Workbook workbook = new Workbook();
  IWorksheet worksheet = workbook.getWorksheets().get(0);
  worksheet.getRange("M1:R16").setValue(sourceData);
  worksheet.getRange("M:R").setColumnWidth(15);
   
  // Create first pivot table with DisplayFieldCaptions = false
  IPivotCache pivotcache1 = workbook.getPivotCaches().create(worksheet.getRange("M1:R16"));
  IPivotTable pivottable1 = worksheet.getPivotTables().add(pivotcache1, worksheet.getRange("A3"), "pivottable1");
  worksheet.getRange("P1:P16").setNumberFormat("$#,##0.00");
  
  // Config first pivot table's fields
  IPivotField field_Category1 = pivottable1.getPivotFields().get("Category");
  field_Category1.setOrientation(PivotFieldOrientation.ColumnField);
  
  IPivotField field_Product1 = pivottable1.getPivotFields().get("Product");
  field_Product1.setOrientation(PivotFieldOrientation.RowField);
  
  IPivotField field_Amount1 = pivottable1.getPivotFields().get("Amount");
  field_Amount1.setOrientation(PivotFieldOrientation.DataField);
  field_Amount1.setNumberFormat("$#,##0.00");
  
  // Set DisplayFieldCaptions to false
  pivottable1.setDisplayFieldCaptions(false);
  worksheet.getRange("A:K").getEntireColumn().autoFit();
  workbook.save("pivotTableWithoutFieldHeaders.xlsx");

Help .NET | Demo .NET | Help Java | Demo Java

Support for Control Tray Selection in PrintOut

DsExcel .NET v9.1 adds support for selecting a printer’s paper source or input tray during PrintOut operations on Windows. This is useful in real-world office environments where printers may have multiple trays for different paper sizes, types, or workflows.

Developers can now use PrintOutOptions.PaperSourceName alongside ActivePrinter to target a specific tray by name. If no tray is specified, the printer uses its default paper source. This feature is supported in .NET on Windows. This matches the capability available in Microsoft Excel's printer properties dialog:

Programmatically Select a printer’s paper source or input tray during PrintOut operations on Windows

C#:

Workbook workbook = new Workbook();
workbook.Open("report.xlsx");

PrintOutOptions options = new PrintOutOptions();
options.ActivePrinter = "Gestetner MP C3503 PCL 6";
options.PaperSourceName = "Tray 2";
options.Copies = 1;

workbook.ActiveSheet.PrintOut(options);

Help .NET | Demo .NET

Support for Picture In-Cell

DsExcel v9.1 introduces support for Picture in-cell, allowing developers to insert images directly into cells and also retrieve their image data on the server side. This supports both Excel-style in-cell image scenarios and workflows where embedded image data needs to be stored or processed elsewhere.

The main API is IRange.CellPicture, which works with the CellPicture class to store image data and alt text. Alt text is also used in operations such as filtering and sorting, and picture-in-cell content is supported in PDF, HTML, and image export. This gives developers a practical new way to work with rich cell content beyond text and formulas.

Excel API Support for Picture In-Cell

C#:

Workbook workbook = new Workbook();
IWorksheet sheet = workbook.ActiveSheet;

// Read image data from file
byte[] imageData = File.ReadAllBytes("photo.png");

// Set picture-in-cell with alt text
sheet.Range["A1"].CellPicture = new CellPicture(imageData, "Product Photo");

// Get picture-in-cell
CellPicture retrieved = sheet.Range["A1"].CellPicture;
Console.WriteLine(retrieved.AltText); // "Product Photo"
byte[] data = retrieved.ImageData;    // image binary data

// Remove picture-in-cell
sheet.Range["A1"].CellPicture = null;

Java:

IWorkbook workbook = new Workbook();
IWorksheet sheet = workbook.getActiveSheet();

// Read image data from file
byte[] imageData = Files.readAllBytes(Paths.get("photo.png"));

// Set picture-in-cell with alt text
sheet.getRange("A1").setCellPicture(new CellPicture(imageData, "Product Photo"));

// Get picture-in-cell
CellPicture retrieved = sheet.getRange("A1").getCellPicture();
System.out.println(retrieved.getAltText()); // "Product Photo"
byte[] data = retrieved.getImageData();     // image binary data

// Remove picture-in-cell
sheet.getRange("A1").setCellPicture(null);

Help .NET | Demo .NET | Help Java | Demo Java


Template Support Improvements

DsExcel v9.1 expands the template engine with more expressive filtering and better support for SpreadJS-authored template content. These improvements help developers keep more logic inside the template itself, reducing preprocessing code and making reports easier to maintain.

This release adds support for NULL, DATETIME, and REGEX in template filters, along with support for expandable SpreadJS cell types and styles in template cells. Together, these changes make template-based reporting more flexible for real-world business data and richer SpreadJS-based layouts.

Template Filter Support for NULL

DsExcel v9.1 adds support for the NULL keyword in template filters, making it easier to distinguish missing values from empty strings or placeholder values. This is especially important in real-world reporting, where optional or incomplete data is common.

NULL can be used with = and <> in template expressions, allowing developers to filter for null and non-null values directly in the template using familiar SQL-style logic. This keeps missing-data handling inside the report definition instead of pushing it back into application code.

Template Filter Support for NULL in Excel APIs

C#:

//create a new workbook
var workbook = new GrapeCity.Documents.Excel.Workbook();

//Load template file FilterNullKeyword.xlsx from resource
var templateFile = GetResourceStream("xlsx\\FilterNullKeyword.xlsx");
workbook.Open(templateFile);

#region datasource
{
    var datasource = new DataTable();
    datasource.Columns.Add(new DataColumn("name", typeof(string)));
    datasource.Columns.Add(new DataColumn("phone", typeof(string)));
    datasource.Columns.Add(new DataColumn("city", typeof(string)));
    datasource.Columns.Add(new DataColumn("amount", typeof(double)));

    datasource.Rows.Add("Alice", "123-456", "New York", 100.0);
    datasource.Rows.Add("Bob", DBNull.Value, "Los Angeles", 200.0);
    datasource.Rows.Add("Charlie", "789-012", "New York", 150.0);
    datasource.Rows.Add("Diana", DBNull.Value, "New York", 300.0);
    datasource.Rows.Add("Eve", "345-678", DBNull.Value, 250.0);
    datasource.Rows.Add("Frank", DBNull.Value, "San Francisco", 175.0);

    workbook.AddDataSource("ds", datasource);
}
#endregion

//Invoke to process the template
workbook.ProcessTemplate();
        
// Save to an excel file
workbook.Save("FilterNullKeyword.xlsx");

Java:

// Create a new workbook
Workbook workbook = new Workbook();
//Load template file FilterNullKeyword.xlsx from resource
InputStream templateFile = this.getResourceStream("xlsx/FilterNullKeyword.xlsx");
workbook.open(templateFile);

Workbook dataWorkbook = new Workbook();
dataWorkbook.open(this.getResourceStream("data/dataContainsNull.xlsx"), OpenFileFormat.Xlsx);
// Each sheet in the dataWorkbook is a data source.
for (IWorksheet worksheet : dataWorkbook.getWorksheets()) {
    ITableDataSource datasource = new SheetTable(worksheet);
    workbook.addDataSource(worksheet.getName(), datasource);
}

// Invoke to process the template
workbook.processTemplate();
    
// Save to an excel file
workbook.save("FilterNullKeyword.xlsx");

Help .NET | Demo .NET | Help Java | Demo Java

Template Filter Support for DATETIME

DsExcel v9.1 introduces DATETIME(...) support in template filters, allowing date and time comparisons directly inside template expressions. This makes it much easier to build reports for date ranges, time windows, and other time-based business scenarios without relying on fragile string comparisons.

The function accepts Excel-compatible date/time formats as well as common API and database formats such as ISO 8601. Developers can use it with standard comparison operators to build exact matches or range-based filters directly in the template.

Developer Excel APIs for .NET and Java - Template Filter Support for DATETIME

C#:

//create a new workbook
var workbook = new GrapeCity.Documents.Excel.Workbook();

//Load template file DateTimeFilter.xlsx from resource
var templateFile = GetResourceStream("xlsx\\DateTimeFilter.xlsx");
workbook.Open(templateFile);

#region datasource
{
    var datasource = new DataTable();
    datasource.Columns.Add(new DataColumn("orderId", typeof(string)));
    datasource.Columns.Add(new DataColumn("customer", typeof(string)));
    datasource.Columns.Add(new DataColumn("orderDate", typeof(DateTime)));
    datasource.Columns.Add(new DataColumn("deliveryTime", typeof(DateTime)));
    datasource.Columns.Add(new DataColumn("amount", typeof(double)));

    datasource.Rows.Add("ORD-001", "Alice", new DateTime(2024, 5, 10, 9, 30, 0), new DateTime(2024, 5, 12, 8, 0, 0), 320.0);
    datasource.Rows.Add("ORD-002", "Bob", new DateTime(2024, 5, 22, 14, 0, 0), new DateTime(2024, 5, 25, 12, 30, 0), 750.0);
    datasource.Rows.Add("ORD-003", "Charlie", new DateTime(2024, 6, 1, 10, 15, 0), new DateTime(2024, 6, 3, 9, 0, 0), 180.0);
    datasource.Rows.Add("ORD-004", "Diana", new DateTime(2024, 6, 5, 16, 45, 0), new DateTime(2024, 6, 8, 14, 0, 0), 1200.0);
    datasource.Rows.Add("ORD-005", "Eve", new DateTime(2024, 6, 15, 10, 30, 0), new DateTime(2024, 6, 18, 10, 30, 0), 450.0);
    datasource.Rows.Add("ORD-006", "Frank", new DateTime(2024, 6, 15, 10, 30, 0), new DateTime(2024, 6, 17, 19, 0, 0), 890.0);
    datasource.Rows.Add("ORD-007", "Grace", new DateTime(2024, 6, 20, 8, 0, 0), new DateTime(2024, 6, 22, 7, 30, 0), 2100.0);
    datasource.Rows.Add("ORD-008", "Henry", new DateTime(2024, 6, 28, 11, 0, 0), new DateTime(2024, 7, 1, 15, 45, 0), 560.0);
    datasource.Rows.Add("ORD-009", "Ivy", new DateTime(2024, 7, 3, 13, 30, 0), new DateTime(2024, 7, 5, 20, 0, 0), 3200.0);
    datasource.Rows.Add("ORD-010", "Jack", new DateTime(2024, 7, 10, 9, 0, 0), new DateTime(2024, 7, 12, 11, 0, 0), 175.0);
    datasource.Rows.Add("ORD-011", "Karen", new DateTime(2024, 7, 18, 15, 0, 0), new DateTime(2024, 7, 20, 16, 30, 0), 640.0);
    datasource.Rows.Add("ORD-012", "Leo", new DateTime(2024, 7, 25, 10, 0, 0), new DateTime(2024, 7, 28, 6, 0, 0), 4800.0);
    datasource.Rows.Add("ORD-013", "Mia", new DateTime(2024, 8, 2, 14, 30, 0), new DateTime(2024, 8, 5, 13, 0, 0), 920.0);
    datasource.Rows.Add("ORD-014", "Nathan", new DateTime(2024, 8, 12, 8, 45, 0), new DateTime(2024, 8, 14, 22, 0, 0), 150.0);
    datasource.Rows.Add("ORD-015", "Olivia", new DateTime(2024, 8, 20, 17, 0, 0), new DateTime(2024, 8, 23, 18, 30, 0), 5000.0);

    workbook.AddDataSource("ds", datasource);
}
#endregion

//Invoke to process the template
workbook.ProcessTemplate();
foreach (var worksheet in workbook.Worksheets)
{
    worksheet.UsedRange.EntireRow.AutoFit();
}
        
// Save to an excel file
workbook.Save("DateTimeFilter.xlsx");

Java:

// Create a new workbook
Workbook workbook = new Workbook();
//Load template file DateTimeFilter.xlsx from resource
InputStream templateFile = this.getResourceStream("xlsx/DateTimeFilter.xlsx");
workbook.open(templateFile);

ITableDataSource datasource = new DateTimeFilterData();
workbook.addDataSource("ds", datasource);

//Invoke to process the template
workbook.processTemplate();

for (IWorksheet worksheet : workbook.getWorksheets()) {
    worksheet.getUsedRange().getEntireRow().autoFit();
}
    
// Save to an excel file
workbook.save("DateTimeFilter.xlsx");

Help .NET | Demo .NET | Help Java | Demo Java

Template Filter Support for REGEX

DsExcel v9.1 adds support for the REGEX keyword in template filters, enabling advanced text pattern matching directly in report templates. This is useful for filtering structured values such as SKUs, invoice numbers, email domains, and other formatted text that goes beyond simple wildcard matching.

Regex matching uses the native engine of each platform, making the feature familiar to .NET and Java developers. This gives template authors a more powerful way to express complex text logic without moving those checks into application code.

Template Filter Support for REGEX

C#:

//create a new workbook
var workbook = new GrapeCity.Documents.Excel.Workbook();

//Load template file FilterRegex.xlsx from resource
var templateFile = GetResourceStream("xlsx\\FilterRegex.xlsx");
workbook.Open(templateFile);

#region datasource
{
    var datasource = new DataTable();
    datasource.Columns.Add(new DataColumn("pid", typeof(string)));
    datasource.Columns.Add(new DataColumn("name", typeof(string)));
    datasource.Columns.Add(new DataColumn("sku", typeof(string)));
    datasource.Columns.Add(new DataColumn("description", typeof(string)));

    datasource.Rows.Add("P001", "Laptop Pro 15", "LP-2024-001", "High performance laptop");
    datasource.Rows.Add("P002", "Laptop Air 13", "LA-2024-002", "Lightweight laptop");
    datasource.Rows.Add("P003", "Phone X100", "PX-2023-100", "Flagship phone");
    datasource.Rows.Add("P004", "Phone SE", "PS-2024-050", "Budget phone");
    datasource.Rows.Add("P005", "Tablet Max 12", "TM-2024-012", "Large screen tablet");
    datasource.Rows.Add("P006", "Monitor 4K-27", "MK-2023-027", "4K monitor 27 inch");
    datasource.Rows.Add("P007", "Keyboard MX", "KM-2024-001", "Mechanical keyboard");

    workbook.AddDataSource("product", datasource);
}
#endregion

//Invoke to process the template
workbook.ProcessTemplate();
foreach (var worksheet in workbook.Worksheets)
{
    worksheet.UsedRange.EntireRow.AutoFit();
}
        
// Save to an excel file
workbook.Save("FilterRegex.xlsx");

Java:

// Create a new workbook
Workbook workbook = new Workbook();
//Load template file FilterRegex.xlsx from resource
InputStream templateFile = this.getResourceStream("xlsx/FilterRegex.xlsx");
workbook.open(templateFile);

ITableDataSource datasource = new FilterRegexData();
workbook.addDataSource("product", datasource);

//Invoke to process the template
workbook.processTemplate();

for (IWorksheet worksheet : workbook.getWorksheets()) {
    worksheet.getUsedRange().getEntireRow().autoFit();
}
    
// Save to an excel file
workbook.save("FilterRegex.xlsx");

Help .NET | Demo .NET | Help Java | Demo Java

Expandable Cell Types and SpreadJS Styles in Template Cells

DsExcel v9.1 adds support for expandable SpreadJS cell types and styles in template cells, helping SpreadJS-authored templates behave more naturally during template expansion. This includes support for CellType, DropDown-related behavior, and several other SpreadJS-specific style settings.

This behavior can be enabled through the workbook defined name TemplateOptions.SpreadJSStyleExpandable. Once enabled, supported SpreadJS styles expand with template data in a way similar to Excel styles, preserving more of the original template design in generated output.

Expandable SpreadJS cell types and styles in template cells Example

C#:

//create a new workbook
var workbook = new GrapeCity.Documents.Excel.Workbook();

//Load template file from resource
var templateFile = this.GetResourceStream("sjs\\Template_SpreadJSStyle.sjs");
workbook.Open(templateFile, OpenFileFormat.Sjs);
workbook.Names.Add("TemplateOptions.SpreadJSStyleExpandable", "True");

#region Define custom class
//public class Student
//{
//    public string Name { get; set; }
//    public int Gender { get; set; }
//    public DateTime Birthday { get; set; }
//    public string Hobbies { get; set; }
//    public Student(string name, int gender, DateTime birthday, string hobbies)
//    {
//        Name = name;
//        Gender = gender;
//        Birthday = birthday;
//        Hobbies = hobbies;
//    }
//}
#endregion

#region Init Data
List<Student> students = new List<Student>()
{
    new Student("Emma Johnson", 0, new DateTime(2016, 3, 15), "Drawing and Reading"),
    new Student("Liam Smith", 1, new DateTime(2015, 8, 22), "Soccer and Video Games"),
    new Student("Olivia Brown", 0, new DateTime(2016, 11, 8), "Dancing and Singing"),
    new Student("Noah Davis", 1, new DateTime(2015, 5, 30), "Swimming and Building Legos"),
    new Student("Sophia Wilson", 0, new DateTime(2016, 7, 12), "Playing Piano and Painting")
};
#endregion
//Add data source
workbook.AddDataSource("ds", students);

//Invoke to process the template
workbook.ProcessTemplate();
        
// Save to a .sjs file
workbook.Save("SpreadJSStyle.sjs");

Java:

Workbook workbook = new Workbook();
workbook.open("template.sjs");
workbook.getNames().add("TemplateOptions.SpreadJSStyleExpandable", "true");
String json = new String(Files.readAllBytes(Paths.get("data.json")), StandardCharsets.UTF_8);
workbook.addDataSource("ds", new JsonDataSource(json));
workbook.processTemplate();
workbook.save("out.sjs");

Help .NET | Demo .NET | Help Java | Demo Java


SpreadJS Lossless I/O Improvements

DsExcel v9.1 continues to improve SpreadJS interoperability with a new set of lossless I/O enhancements for SJS and SSJSON workflows. These updates help preserve newer SpreadJS workbook features more accurately during import, export, and format conversion.

This release adds support for Sparkline conditional formatting preservation, Top/Bottom Percent rules, Scrollbar Auto mode, the new DataManager storage format, accounting underline styles, and Named Cell Templates. These improvements help reduce feature loss when moving workbooks between SpreadJS and server-side DsExcel workflows.

Support I/O for Sparkline Rules in Conditional Formatting

DsExcel v9.1 adds lossless SJS and SSJSON I/O support for Sparkline conditional formatting rules, helping preserve these newer SpreadJS visual rules during round-trip processing. Support applies where relevant across Worksheet, TableSheet, and ReportSheet scenarios.

When exporting to XLSX, these Sparkline rules are converted to Data Bar rules, preserving the applied range, data source, and priority, while Sparkline-specific visual settings are not retained. This provides a practical balance between SpreadJS preservation and Excel compatibility.

Support Top/Bottom Percent Rule in Conditional Formatting

DsExcel v9.1 improves SpreadJS compatibility by adding support for Top/Bottom Percent conditional formatting rules in SJS and SSJSON workflows. This aligns better with both SpreadJS behavior and Excel’s Top 10 rule logic by percent.

The enhancement focuses on preserving these rules during import, export, and SJS/SSJSON conversion, without requiring any new public API. This helps developers round-trip ranking-based conditional formatting more reliably across client and server workflows.

Support SpreadJS Scrollbar Auto Mode

DsExcel v9.1 adds support for SpreadJS scrollbar Auto mode in SJS and SSJSON files, preserving the three-state visibility model used by SpreadJS. This helps maintain more of the original workbook UI behavior during round-trip processing.

Because Excel only supports show and hide states, Auto mode is converted to Show during XLSX export. Even with that limitation, the feature improves fidelity when staying within SpreadJS-oriented file formats.

Support the New SJS DataManager Attachments-Per-Table-File Format

DsExcel v9.1 adds support for the newer DataManager attachments-per-table-file format introduced in SpreadJS. In this model, table data is stored as separate attachment files rather than being embedded directly in workbook.json.

DsExcel now supports both the old and new SJS storage models, while preserving the original structure of imported files when saving back to SJS. This improves compatibility with modern DataManager-backed SpreadJS workbooks while avoiding unexpected format conversion.

Support Single and Double Accounting Underline Cell Styles

DsExcel v9.1 adds support for SingleAccounting and DoubleAccounting underline styles in SJS and SSJSON import/export, improving alignment with newer SpreadJS styling behavior. This helps preserve more precise underline formatting when moving content between Excel and SpreadJS formats.

These accounting underline variants are now preserved correctly in JSON-based workflows, although PDF, HTML, and image export still render them the same as standard single and double underlines. Even so, the update improves style fidelity in workbook round-tripping scenarios.

Support I/O for Named Cell Templates

DsExcel v9.1 adds lossless SJS and SSJSON I/O support for Named Cell Templates, helping preserve workbook-level reusable template definitions created in SpreadJS. This is especially useful in template-driven workflows where those definitions should survive server-side processing unchanged.

The feature preserves the namedCellTemplates node during import, export, and SJS/SSJSON conversion, without implementing template authoring behavior directly in DsExcel. This keeps workbook-level definitions intact while maintaining compatibility with SpreadJS-authored content.


New Pivot Table Features Support in DsDataViewer

Interact with Pivot Tables in DsDataViewer

Document Solutions DataViewer (DsDataViewer) v9.1 adds support for interacting with PivotTables, giving users more control over pivot-based reports directly in the viewer. With this enhancement, users can work with PivotTables in a more dynamic way by performing actions such as filtering, sorting, using slicers, and changing the layout without leaving the viewing experience.

This feature is available for Professional license users and follows the permissions defined in the source workbook. If sheet protection is disabled, PivotTable interactions are allowed. If protection is enabled, PivotTable interactions depend on whether the workbook’s Use PivotTable option is selected. This helps preserve workbook-level authoring intent while still allowing interactive analysis where permitted.

DsDataViewer supports PivotTable interaction through both the Filter button and the PivotTable panel. When a workbook opens and the active cell is already inside a PivotTable, the panel opens automatically. Clicking within a PivotTable range opens the panel, while clicking outside of it closes the panel. Users can add fields by checking or dragging them, modify the PivotTable layout, apply filters, adjust field settings, and continue working smoothly even when layout changes require DsDataViewer to automatically expand the visible rows and columns to fit the updated PivotTable structure.

Pivot Table Panel Opening/Closing

Pivot Table Panel Opening/Closing in JavaScript Data Viewer | Developer Solution

Pivot Table Add Fields by Checking or Dragging

Pivot Table Add Fields by Checking or Dragging in Professional Data Viewer

Modify Pivot Table Layout

Allow Users to Modify Pivot Table Layout in JS Applications

Pivot Table Filters

Allow Pivot Table Filters in JavaScript Client-Side Applications

Pivot Table Field Settings

Pivot Table Field Settings | JavaScript Developer UI/UX Solution

Pivot Table Color Theme Switching

JavaScript Developers Pivot Table UX/UI Theme Switching

With support for PivotTable interaction, DsDataViewer v9.1 makes it easier for users to explore and adjust PivotTable-based reports directly in the viewer, bringing a more interactive spreadsheet analysis experience to web-based document viewing.

Help | Demo


Ready to Try DsExcel v9.1?

With support for modern Excel features, richer template filtering, improved export fidelity, and stronger SpreadJS interoperability, DsExcel v9.1 makes it easier to build advanced spreadsheet solutions across .NET and Java. From interactive worksheet features like cell checkboxes and picture-in-cell or interactive pivot table support in client-side viewing, to smarter template processing and more reliable JSON round-tripping, this release delivers practical improvements for both report generation and end-user workbook experiences.

Ready to explore the release? Download the latest .NET or Java edition of Document Solutions for Excel today.

Tags:

comments powered by Disqus