Browse our Products

Aspose.Words for .NET 23.5 Release Notes

Major Features

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

  • Provided the feature to get and modify chart series data.
  • Implemented support for text wrapping in headers/footers.
  • Fixed rendering of MathML formula with embedded images.
  • Added an ability to remove digital signatures from ODT documents.
  • Added public properties to obtain base and ruby text of phonetic guide Run.

Full List of Issues Covering all Changes in this Release

Public API and Backward Incompatible Changes

This section lists public API changes that were introduced in Aspose.Words 23.5. 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 ability to remove digital signatures from ODT

Related issue: WORDSNET-25043

Implemented removing digital signatures from ODT using Aspose.Words.DigitalSignatures.DigitalSignatureUtil.RemoveAllSignatures method.

DigitalSignatureUtil.RemoveAllSignatures("in.odt", "out.odt");

Added new public property FindReplaceOptions.IgnoreShapes

Related issue: WORDSNET-25115

The following public property was added to Aspose.Words.Replacing.FindReplaceOptions class:

/// <summary>
/// <para>Gets or sets a boolean value indicating either to ignore shapes within a text.</para>
/// <para>The default value is <c>false</c>.</para>
/// </summary>
public bool IgnoreShapes { get; set; }
DocumentBuilder builder = new DocumentBuilder();
builder.Write("123");
builder.InsertShape(ShapeType.Balloon, 200, 200);
builder.Write("456");

builder.Document.Range.Replace("123456", "789", new FindReplaceOptions() { IgnoreShapes = true });
Console.Write(builder.Document.GetText());

// This code produces the following output:
// 789
// \u000c

Added new public property Forms2OleControl.GroupName

Related issue: WORDSNET-25165

The following public property was added to Aspose.Words.Drawing.Ole.Forms2OleControl class:

/// <summary>
/// Gets or sets a string that specifies a group of mutually exclusive controls.
/// The default value is an empty string.
/// </summary>
public string GroupName {get; set;}
// Assume there is a shape with Forms2OleControl in document.
Document doc = new Document("input.docx");

Shape shape = (Shape)doc.GetChild(NodeType.Shape, 0, true);
Forms2OleControl control = (Forms2OleControl)shape.OleFormat.OleControl;

if (control != null)
{
    Console.WriteLine("Control group name is: {0}", control.GroupName);
    control.GroupName = "newGroup";
}

Added new public property PdfSaveOptions.ExportParagraphGraphicsToArtifact

Related issue: WORDSNET-25280

The following public property was added to Aspose.Words.Saving.PdfSaveOptions class:

/// <summary>
/// Gets or sets a value determining whether a paragraph graphic should be marked as an artifact.
/// </summary>
/// <remarks>
/// <para> Default value is <c>false</c> and paragraph graphics (underlines, text emphasis, etc.)
/// will be marked as "Span" in the logical structure of the document.</para>
/// <para> When the value is <c>true</c> the paragraph graphics will be marked as "Artifact".</para>
/// <para> This value is ignored when <see cref="ExportDocumentStructure"/> is <c>false</c>. </para>
/// </remarks>
public bool ExportParagraphGraphicsToArtifact { get; set; }
Document doc = new Document(fileName);
PdfSaveOptions saveOptions = new PdfSaveOptions();
saveOptions.ExportParagraphGraphicsToArtifact = true;
doc.Save(outputFileName, saveOptions);

Added public properties to obtain base and ruby text of phonetic guide Run

Related issue: WORDSNET-25173

The following public property was added to Aspose.Words.Run class:

/// <summary>
/// Gets a <see cref="PhoneticGuide"/> object.
/// </summary>
public PhoneticGuide PhoneticGuide { get; }

Added the following public class into Aspose.Words namespace:

/// <summary>
/// Represents Phonetic Guide.
/// </summary>
public class PhoneticGuide
{
  /// <summary>
  /// Gets base text of the phonetic guide.
  /// </summary>
  public string BaseText { get; }

  /// <summary>
  /// Gets ruby text of the phonetic guide.
  /// </summary>
  public string RubyText { get; }
}
Document doc = new Document("DocWithRuby.docx");

Run run = doc.FirstSection.Body.FirstParagraph.Runs[0];
if (run != null)
{
    Console.WriteLine(run.PhoneticGuide.BaseText);
    Console.WriteLine(run.PhoneticGuide.RubyText);
}

Added public property ChartSeries.SeriesType of new ChartSeriesType enum type

Related issue: WORDSNET-24945

The SeriesType property has been added to the ChartSeries class:

/// <summary>
/// Gets the type of this chart series.
/// </summary>
public ChartSeriesType SeriesType { get; }

The definition of the added ChartSeriesType enum type:

/// <summary>
/// Specifies a type of a chart series.
/// </summary>
public enum ChartSeriesType
{
    /// <summary>
    /// Represents an Area chart series.
    /// </summary>
    Area,

    /// <summary>
    /// Represents a Stacked Area chart series.
    /// </summary>
    AreaStacked,

    /// <summary>
    /// Represents a 100% Stacked Area chart series.
    /// </summary>
    AreaPercentStacked,

    /// <summary>
    /// Represents a 3D Area chart series.
    /// </summary>
    Area3D,

    /// <summary>
    /// Represents a 3D Stacked Area chart series.
    /// </summary>
    Area3DStacked,

    /// <summary>
    /// Represents a 3D 100% Stacked Area chart series.
    /// </summary>
    Area3DPercentStacked,

    /// <summary>
    /// Represents a Bar chart series.
    /// </summary>
    Bar,

    /// <summary>
    /// Represents a Stacked Bar chart series.
    /// </summary>
    BarStacked,

    /// <summary>
    /// Represents a 100% Stacked Bar chart series.
    /// </summary>
    BarPercentStacked,

    /// <summary>
    /// Represents a 3D Bar chart series.
    /// </summary>
    Bar3D,

    /// <summary>
    /// Represents a 3D Stacked Bar chart series.
    /// </summary>
    Bar3DStacked,

    /// <summary>
    /// Represents a 3D 100% Stacked Bar chart series.
    /// </summary>
    Bar3DPercentStacked,

    /// <summary>
    /// Represents a Bubble chart series.
    /// </summary>
    Bubble,

    /// <summary>
    /// Represents a 3D Bubble chart series.
    /// </summary>
    Bubble3D,

    /// <summary>
    /// Represents a Column chart series.
    /// </summary>
    Column,

    /// <summary>
    /// Represents a Stacked Column chart series.
    /// </summary>
    ColumnStacked,

    /// <summary>
    /// Represents a 100% Stacked Column chart series.
    /// </summary>
    ColumnPercentStacked,

    /// <summary>
    /// Represents a 3D Column chart series.
    /// </summary>
    Column3D,

    /// <summary>
    /// Represents a 3D Stacked Column chart series.
    /// </summary>
    Column3DStacked,

    /// <summary>
    /// Represents a 3D 100% Stacked Column chart series.
    /// </summary>
    Column3DPercentStacked,

    /// <summary>
    /// Represents a 3D Clustered Column chart series.
    /// </summary>
    Column3DClustered,

    /// <summary>
    /// Represents a Doughnut chart series.
    /// </summary>
    Doughnut,

    /// <summary>
    /// Represents a Line chart series.
    /// </summary>
    Line,

    /// <summary>
    /// Represents a Stacked Line chart series.
    /// </summary>
    LineStacked,

    /// <summary>
    /// Represents a 100% Stacked Line chart series.
    /// </summary>
    LinePercentStacked,

    /// <summary>
    /// Represents a 3D Line chart series.
    /// </summary>
    Line3D,

    /// <summary>
    /// Represents a Pie chart series.
    /// </summary>
    Pie,

    /// <summary>
    /// Represents a 3D Pie chart series.
    /// </summary>
    Pie3D,

    /// <summary>
    /// Represents a Pie of Bar chart series.
    /// </summary>
    PieOfBar,

    /// <summary>
    /// Represents a Pie of Pie chart series.
    /// </summary>
    PieOfPie,

    /// <summary>
    /// Represents a Radar chart series.
    /// </summary>
    Radar,

    /// <summary>
    /// Represents a Scatter chart series.
    /// </summary>
    Scatter,

    /// <summary>
    /// Represents a Stock chart series.
    /// </summary>
    Stock,

    /// <summary>
    /// Represents a Surface chart series.
    /// </summary>
    Surface,

    /// <summary>
    /// Represents a 3D Surface chart series.
    /// </summary>
    Surface3D,

    /// <summary>
    /// Represents a Treemap chart series.
    /// </summary>
    Treemap,

    /// <summary>
    /// Represents a Sunburst chart series.
    /// </summary>
    Sunburst,

    /// <summary>
    /// Represents a Histogram chart series.
    /// </summary>
    Histogram,

    /// <summary>
    /// Represents a Pareto chart series.
    /// </summary>
    Pareto,

    /// <summary>
    /// Represents a Pareto Line chart series.
    /// </summary>
    ParetoLine,

    /// <summary>
    /// Represents a Box and Whisker chart series.
    /// </summary>
    BoxAndWhisker,

    /// <summary>
    /// Represents a Waterfall chart series.
    /// </summary>
    Waterfall,

    /// <summary>
    /// Represents a Funnel chart series.
    /// </summary>
    Funnel,

    /// <summary>
    /// Represents a Region Map chart series.
    /// </summary>
    RegionMap
}
Document doc = new Document("ComboChart.docx");
Shape shape = (Shape)doc.GetChild(NodeType.Shape, 0, true);
Chart chart = shape.Chart;

// Remove all series of the Column type.
for (int i = chart.Series.Count - 1; i >= 0; i--)
{
    if (chart.Series[i].SeriesType == ChartSeriesType.Column)
        chart.Series.RemoveAt(i);
}

// Add a new series.
chart.Series.Add(
    "New Series",
    new string[] { "Category 1", "Category 2", "Category 3", "Category 4" },
    new double[] { 5.6, 7.1, 2.9, 8.9 });

doc.Save("out.docx");

Implemented ability to get and modify chart series data

Related issue: WORDSNET-18468

The following changes have been implemented:

Added new classes: ChartXValue, ChartYValue, ChartXValueCollection, ChartYValueCollection, BubbleSizeCollection, ChartMultilevelValue, and new enum types: ChartXValueType, ChartYValueType.

Added new properties and methods to the ChartSeries class.

namespace Aspose.Words.Drawing.Charts
{
    public class ChartSeries
    {
        /// <summary>
        /// Adds the specified X value to the chart series. If the series supports Y values and bubble sizes, they will
        /// be empty for the X value.
        /// </summary>
        public void Add(ChartXValue xValue);

        /// <summary>
        /// Adds the specified X and Y values to the chart series.
        /// </summary>
        public void Add(ChartXValue xValue, ChartYValue yValue);

        /// <summary>
        /// Adds the specified X value, Y value and bubble size to the chart series.
        /// </summary>
        public void Add(ChartXValue xValue, ChartYValue yValue, double bubbleSize);

        /// <summary>
        /// Inserts the specified X value into the chart series at the specified index. If the series supports Y values
        /// and bubble sizes, they will be empty for the X value.
        /// </summary>
        /// <remarks>
        /// The corresponding data point with default formatting will be inserted into the data point collection. And,
        /// if data labels are displayed, the corresponding data label with default formatting will be inserted too.
        /// </remarks>
        public void Insert(int index, ChartXValue xValue);

        /// <summary>
        /// Inserts the specified X and Y values into the chart series at the specified index.
        /// </summary>
        /// <remarks>
        /// The corresponding data point with default formatting will be inserted into the data point collection. And,
        /// if data labels are displayed, the corresponding data label with default formatting will be inserted too.
        /// </remarks>
        public void Insert(int index, ChartXValue xValue, ChartYValue yValue);

        /// <summary>
        /// Inserts the specified X value, Y value and bubble size into the chart series at the specified index.
        /// </summary>
        /// <remarks>
        /// The corresponding data point with default formatting will be inserted into the data point collection. And,
        /// if data labels are displayed, the corresponding data label with default formatting will be inserted too.
        /// </remarks>
        public void Insert(int index, ChartXValue xValue, ChartYValue yValue, double bubbleSize);

        /// <summary>
        /// Removes the X value, Y value, and bubble size, if supported, from the chart series at the specified index.
        /// The corresponding data point and data label are also removed.
        /// </summary>
        public void Remove(int index);

        /// <summary>
        /// Removes all data values from the chart series. Format of all individual data points and data labels is cleared.
        /// </summary>
        public void Clear();

        /// <summary>
        /// Removes all data values from the chart series with preserving the format of the data points and data labels.
        /// </summary>
        public void ClearValues();

        /// <summary>
        /// Gets a collection of X values for this chart series.
        /// </summary>
        public ChartXValueCollection XValues { get; }

        /// <summary>
        /// Gets a collection of Y values for this chart series.
        /// </summary>
        public ChartYValueCollection YValues { get; }

        /// <summary>
        /// Gets a collection of bubble sizes for this chart series.
        /// </summary>
        public BubbleSizeCollection BubbleSizes { get; }

        ...
    }

    /// <summary>
    /// Allows to specify type of an X value of a chart series.
    /// </summary>
    public enum ChartXValueType
    {
        /// <summary>
        /// Specifies that an X value is a string category.
        /// </summary>
        String,

        /// <summary>
        /// Specifies that an X value is a double-precision floating-point number.
        /// </summary>
        Double,

        /// <summary>
        /// Specifies that an X value is a date and time of day.
        /// </summary>
        DateTime,

        /// <summary>
        /// Specifies that an X value is a time of day.
        /// </summary>
        Time,

        /// <summary>
        /// Specifies that an X value is a multilevel value.
        /// </summary>
        /// <seealso cref="ChartMultilevelValue"/>
        Multilevel
    }

    /// <summary>
    /// Allows to specify type of an Y value of a chart series.
    /// </summary>
    public enum ChartYValueType
    {
        /// <summary>
        /// Specifies that an Y value is a double-precision floating-point number.
        /// </summary>
        Double,

        /// <summary>
        /// Specifies that an Y value is a date and time of day.
        /// </summary>
        DateTime,

        /// <summary>
        /// Specifies that an X value is a time of day.
        /// </summary>
        Time
    }

    /// <summary>
    /// Represents an X value for a chart series.
    /// </summary>
    /// <remarks>
    /// This class contains a number of static methods for creating an X value of a particular type. The
    /// <see cref="ValueType"/> property allows you to determine the type of an existing X value.
    /// All non-null X values of a chart series must be of the same <see cref="ChartXValueType"/> type.
    /// </remarks>
    public class ChartXValue
    {
        /// <summary>
        /// Creates a <see cref="ChartXValue"/> instance of the <see cref="ChartXValueType.String"/> type.
        /// </summary>
        public static ChartXValue FromString(string value);

        /// <summary>
        /// Creates a <see cref="ChartXValue"/> instance of the <see cref="ChartXValueType.Double"/> type.
        /// </summary>
        public static ChartXValue FromDouble(double value);

        /// <summary>
        /// Creates a <see cref="ChartXValue"/> instance of the <see cref="ChartXValueType.DateTime"/> type.
        /// </summary>
        public static ChartXValue FromDateTime(DateTime value);

        /// <summary>
        /// Creates a <see cref="ChartXValue"/> instance of the <see cref="ChartXValueType.Time"/> type.
        /// </summary>
        public static ChartXValue FromTimeSpan(TimeSpan value);

        /// <summary>
        /// Creates a <see cref="ChartXValue"/> instance of the <see cref="ChartXValueType.Multilevel"/> type.
        /// </summary>
        public static ChartXValue FromMultilevelValue(ChartMultilevelValue value);

        /// <summary>
        /// Gets the type of the X value stored in the object.
        /// </summary>
        public ChartXValueType ValueType { get; }

        /// <summary>
        /// Gets the stored string value.
        /// </summary>
        public string StringValue { get; }

        /// <summary>
        /// Gets the stored numeric value.
        /// </summary>
        public double DoubleValue { get; }

        /// <summary>
        /// Gets the stored datetime value.
        /// </summary>
        public DateTime DateTimeValue { get; }

        /// <summary>
        /// Gets the stored time value.
        /// </summary>
        public TimeSpan TimeValue { get; }

        /// <summary>
        /// Gets the stored multilevel value.
        /// </summary>
        public ChartMultilevelValue MultilevelValue { get; }
    }

    /// <summary>
    /// Represents an Y value for a chart series.
    /// </summary>
    /// <remarks>
    /// This class contains a number of static methods for creating an Y value of a particular type. The
    /// <see cref="ValueType"/> property allows you to determine the type of an existing Y value.
    /// All non-null Y values of a chart series must be of the same <see cref="ChartYValueType"/> type.
    /// </remarks>
    public class ChartYValue
    {
        /// <summary>
        /// Creates a <see cref="ChartYValue"/> instance of the <see cref="ChartYValueType.Double"/> type.
        /// </summary>
        public static ChartYValue FromDouble(double value);

        /// <summary>
        /// Creates a <see cref="ChartYValue"/> instance of the <see cref="ChartYValueType.DateTime"/> type.
        /// </summary>
        public static ChartYValue FromDateTime(DateTime value);

        /// <summary>
        /// Creates a <see cref="ChartYValue"/> instance of the <see cref="ChartYValueType.Time"/> type.
        /// </summary>
        public static ChartYValue FromTimeSpan(TimeSpan value);

        /// <summary>
        /// Gets the type of the Y value stored in the object.
        /// </summary>
        public ChartYValueType ValueType { get; }

        /// <summary>
        /// Gets the stored numeric value.
        /// </summary>
        public double DoubleValue { get; }

        /// <summary>
        /// Gets the stored datetime value.
        /// </summary>
        public DateTime DateTimeValue { get; }

        /// <summary>
        /// Gets the stored time value.
        /// </summary>
        public TimeSpan TimeValue { get; }
    }

    /// <summary>
    /// Represents a collection of X values for a chart series.
    /// </summary>
    /// <remarks>
    /// All items of the collection other than <b>null</b> must have the same <see cref="ChartXValue.ValueType"/>.
    /// The collection allows only changing X values. To add or insert new values to a chart series, or remove values,
    /// the appropriate methods of the <see cref="ChartSeries"/> class can be used.
    /// </remarks>
    public class ChartXValueCollection : IEnumerable<ChartXValue>
    {
        /// <summary>
        /// Gets the number of items in this collection.
        /// </summary>
        public int Count { get; }

        /// <summary>
        /// Gets or sets the X value at the specified index.
        /// </summary>
        /// <remarks>
        /// Empty values are represented as <b>null</b>.
        /// </remarks>
        public ChartXValue this[int index] { get; set; }
    }

    /// <summary>
    /// Represents a collection of Y values for a chart series.
    /// </summary>
    /// <remarks>
    /// All items of the collection other than <b>null</b> must have the same <see cref="ChartYValue.ValueType"/>.
    /// The collection allows only changing Y values. To add or insert new values to a chart series, or remove values,
    /// the appropriate methods of the <see cref="ChartSeries"/> class can be used.
    /// </remarks>
    public class ChartYValueCollection : IEnumerable<ChartYValue>
    {
        /// <summary>
        /// Gets the number of items in this collection.
        /// </summary>
        public int Count { get; }

        /// <summary>
        /// Gets or sets the Y value at the specified index.
        /// </summary>
        /// <remarks>
        /// Empty values are represented as <b>null</b>.
        /// </remarks>
        public ChartYValue this[int index] { get; set; }
    }

    /// <summary>
    /// Represents a collection of bubble sizes for a chart series.
    /// </summary>
    /// <remarks>
    /// The collection allows only changing bubble sizes. To add or insert new values to a chart series, or remove
    /// values, the appropriate methods of the <see cref="ChartSeries"/> class can be used.
    /// Empty bubble size values are represented as <see cref="double.NaN"/>.
    /// </remarks>
    public class BubbleSizeCollection : IEnumerable<double>
    {
        /// <summary>
        /// Gets the number of items in this collection.
        /// </summary>
        public int Count { get; }

        /// <summary>
        /// Gets or sets the bubble size value at the specified index.
        /// </summary>
        public double this[int index] { get; set; }
    }

    /// <summary>
    /// Represents a value for charts that display multilevel data.
    /// </summary>
    public class ChartMultilevelValue
    {
        /// <summary>
        /// Initializes a new instance of this class that represents a three-level value.
        /// </summary>
        public ChartMultilevelValue(string level1, string level2, string level3);

        /// <summary>
        /// Initializes a new instance of this class that represents a two-level value.
        /// </summary>
        public ChartMultilevelValue(string level1, string level2);

        /// <summary>
        /// Initializes a new instance of this class that represents a single-level value.
        /// </summary>
        public ChartMultilevelValue(string level1);

        /// <summary>
        /// Gets the name of the chart top level that this value refers to.
        /// </summary>
        public string Level1 { get; }

        /// <summary>
        /// Gets the name of the chart intermediate level that this value refers to.
        /// </summary>
        public string Level2 { get; }

        /// <summary>
        /// Gets the name of the chart bottom level that this value refers to.
        /// </summary>
        public string Level3 { get; }
    }
}
Document doc = new Document("ScatterChart.docx");

Shape shape = (Shape)doc.GetChild(NodeType.Shape, 0, true);
Chart chart = shape.Chart;
ChartSeries series1 = chart.Series[0];

// Clear X and Y values of the first series.
series1.ClearValues();

// Populate the series with data.
series1.Add(ChartXValue.FromDouble(3), ChartYValue.FromDouble(10));
series1.Add(ChartXValue.FromDouble(5), ChartYValue.FromDouble(5));
series1.Add(ChartXValue.FromDouble(7), ChartYValue.FromDouble(11));
series1.Add(ChartXValue.FromDouble(9), ChartYValue.FromDouble(17));

ChartSeries series2 = chart.Series[1];

// Clear X and Y values of the second series.
series2.ClearValues();

// Populate the series with data.
series2.Add(ChartXValue.FromDouble(2), ChartYValue.FromDouble(4));
series2.Add(ChartXValue.FromDouble(4), ChartYValue.FromDouble(7));
series2.Add(ChartXValue.FromDouble(6), ChartYValue.FromDouble(14));
series2.Add(ChartXValue.FromDouble(8), ChartYValue.FromDouble(7));

doc.Save("out.docx");
Document doc = new Document("Chart.docx");

Shape shape = (Shape)doc.GetChild(NodeType.Shape, 0, true);
Chart chart = shape.Chart;
ChartSeries series = chart.Series[0];

double minValue = Double.MaxValue;
int minValueIndex = 0;
double maxValue = Double.MinValue;
int maxValueIndex = 0;

for (int i = 0; i < series.YValues.Count; i++)
{
    // Clear individual format of all data points. Data points and data values are one-to-one in column charts.
    series.DataPoints[i].ClearFormat();

    // Get Y value.
    double yValue = series.YValues[i].DoubleValue;

    if (yValue < minValue)
    {
        minValue = yValue;
        minValueIndex = i;
    }

    if (yValue > maxValue)
    {
        maxValue = yValue;
        maxValueIndex = i;
    }
}

// Change colors of the max and min values.
series.DataPoints[minValueIndex].Format.Fill.ForeColor = Color.Red;
series.DataPoints[maxValueIndex].Format.Fill.ForeColor = Color.Green;

doc.Save("out.docx");
Document doc = new Document("SalesChart.docx");

Shape shape = (Shape)doc.GetChild(NodeType.Shape, 0, true);
Chart chart = shape.Chart;
ChartSeries department1Series = chart.Series[0];
ChartSeries department2Series = chart.Series[1];

// Remove the first value in the both series.
department1Series.Remove(0);
department2Series.Remove(0);

// Add new values to the both series.
ChartXValue newXCategory = ChartXValue.FromString("Q1, 2023");
department1Series.Add(newXCategory, ChartYValue.FromDouble(10.3));
department2Series.Add(newXCategory, ChartYValue.FromDouble(5.7));

doc.Save("out.docx");