Browse our Products

Aspose.Words for Python via .NET 23.4 Release Notes

Major Features

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

  • Added an ability to set distance between table and surrounding text.
  • Provided an ability to determine whether a Run is a phonetic guide run.
  • Implemented the simple way to work with series and axes of a combo charts.
  • Provided the new public properties connected to the shape relative positioning and sizing.
  • Improved accuracy and performance of color brightness calculation for automatic text color resolution in accordance with the latest versions of MS Word.

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 for Python via .NET 23.4. 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 for Python via .NET 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 set distance between table and surrounding text

Now you can set the following properties of the Table class:

@property
def distance_left(self) -> float:
    '''Gets or sets distance between table left and the surrounding text, in points.'''
    ...
    
@distance_left.setter
def distance_left(self, value: float):
    ...
    
@property
def distance_right(self) -> float:
    '''Gets or sets distance between table right and the surrounding text, in points.'''
    ...
    
@distance_right.setter
def distance_right(self, value: float):
    ...
    
@property
def distance_top(self) -> float:
    '''Gets or sets distance between table top and the surrounding text, in points.'''
    ...
    
@distance_top.setter
def distance_top(self, value: float):
    ...
    
@property
def distance_bottom(self) -> float:
    '''Gets or sets distance between table bottom and the surrounding text, in points.'''
    ...
    
@distance_bottom.setter
def distance_bottom(self, value: float):
    ...

Please note: setting these properties makes the table floating.

from aspose.words import Document

doc = Document("input.docx")
table = doc.first_section.body.tables[0]

# Set distance between table and surrounding text.
table.distance_left = 24
table.distance_right = 24
table.distance_top = 3
table.distance_bottom = 3

doc.save("output.docx")

Added public property GradientStop.base_color

The following public property was added to aspose.words.drawing.GradientStop class:

@property
def base_color(self) -> aspose.pydrawing.Color:
    '''Gets a value representing the color of the gradient stop without any modifiers.'''
    ...
from aspose.words import DocumentBuilder
from aspose.words.drawing import ShapeType, GradientStop, GradientStyle, GradientVariant
from aspose.pydrawing import Color
    
builder = DocumentBuilder()
shape = builder.insert_shape(ShapeType.BALLOON, width=300, height=300)

# Set stroke thickness to 7pt.
shape.stroke.weight = 7

# Fill the stroke with one-color gradient.
shape.stroke.fill.one_color_gradient(Color.red, GradientStyle.HORIZONTAL, GradientVariant.VARIANT1, 0.1)

# In OneColorGradient the second color is set automatically by adding to the first color either tint or shade.
# So, we can check unmodified color is actually those we set to the first color.
gradientStop = shape.stroke.fill.gradient_stops[1]

print(f"The color is: Color [A={gradientStop.color.a}, R={gradientStop.color.r}, G={gradientStop.color.g}, "
      f"B={gradientStop.color.b}]")
print(f"The base (unmodified) color is: Color [A={gradientStop.base_color.a}, R={gradientStop.base_color.r}, "
      f"G={gradientStop.base_color.g} B={gradientStop.base_color.b}]")

''' This code produces the following output:
The color is: Color [A=255, R=51, G=0, B=0]
The base (unmodified) color is: Color [A=255, R=255, G=0, B=0]
'''

Added public property Run.is_phonetic_guide

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

 @property
def is_phonetic_guide(self) -> bool:
    '''Gets a boolean value indicating either the run is a phonetic guide.'''
    ...
from aspose.words import DocumentBuilder

builder = DocumentBuilder()
builder.write("text")
run = builder.document.first_section.body.first_paragraph.runs[0]
print(f"The phonetic guide value of the run is '{run.is_phonetic_guide}'")

''' This code produces the following output:
The phonetic guide value of the run is 'False' '''

Added public property Stroke.fill

The following public property was added to aspose.words.drawing.Stroke class:

@property
def fill(self) -> aspose.words.drawing.Fill:
    '''Gets fill formatting for the :class:`Stroke`.'''
    ...
from aspose.words import DocumentBuilder
from aspose.words.drawing import ShapeType, GradientStyle, GradientVariant
from aspose.pydrawing import Color

builder = DocumentBuilder()
shape = builder.insert_shape(ShapeType.BALLOON, width=300, height=300)

# Set stroke thickness to 7pt.
shape.stroke.weight = 7

# Fill the stroke with two - color gradient.
shape.stroke.fill.two_color_gradient(Color.red, Color.blue, GradientStyle.HORIZONTAL, GradientVariant.VARIANT1)

builder.document.save("GradientStroke.docx")

Improvements in Chart class for Combo charts

The following changes have been implemented:

  • A ChartSeriesCollection instance returned by the Chart.series property includes all series of a combo chart, not just those of a main chart type.
  • Implemented the ChartAxisCollection class. Added the Chart.axes property of this type, which allows access to all axes of a combo chart.
@property
def axes(self) -> aspose.words.drawing.charts.ChartAxisCollection:
    '''Gets a collection of all axes of this chart.'''
    ...

class ChartAxisCollection:
    '''Represents a collection of chart axes.'''
    
    def __getitem__(self, index: int) -> aspose.words.drawing.charts.ChartAxis:
        '''Gets the axis at the specified index.'''
        ...
    
    @property
    def count(self) -> int:
        '''Gets the number of axes in this collection.'''
        ...
    ...
from aspose.words import Document, NodeType
from aspose.words.drawing.charts import MarkerSymbol, ChartAxisType

doc = Document("ComboChart.docx")
shape = doc.get_child_nodes(NodeType.SHAPE, True)[0].as_shape()
chart = shape.chart

# Show markers in the line series named 'Series 3'.
for series in chart.series:
    if series.name == 'Series 3':
        series.marker.symbol = MarkerSymbol.CIRCLE
        series.marker.size = 18
        break

# Hide the major grid lines on the primary and secondary Y axes.
    for axis in chart.axes:
        if axis.type == ChartAxisType.VALUE:
            axis.has_major_gridlines = False

doc.save("output.docx")

New public properties for working with the shape relative positioning and sizing have been added

New public properties relative_horizontal_size and relative_vertical_size for specifying the relative size binding of the shape have been added to the Shape class:

@property
def relative_horizontal_size(self) -> aspose.words.drawing.RelativeHorizontalSize:
    '''Gets or sets the value of shape's relative size in horizontal direction.
    
    The default value is :class:`RelativeHorizontalSize`.
    
    Has effect only if :attr:`ShapeBase.width_relative` is set.'''
    ...

@relative_horizontal_size.setter
def relative_horizontal_size(self, value: aspose.words.drawing.RelativeHorizontalSize):
    ...

@property
def relative_vertical_size(self) -> aspose.words.drawing.RelativeVerticalSize:
    '''Gets or sets the value of shape's relative size in vertical direction.
    
    The default value is :attr:`RelativeVerticalSize.MARGIN`.
    
    Has effect only if :attr:`ShapeBase.height_relative` is set.'''
    ...

@relative_vertical_size.setter
def relative_vertical_size(self, value: aspose.words.drawing.RelativeVerticalSize):
    ...

New public properties height_relative and width_relative for specifying the shape relative size in percent have been added to the Shape class:

@property
def height_relative(self) -> float:
    '''Gets or sets the value that represents the percentage of shape's relative height.'''
    ...

@height_relative.setter
def height_relative(self, value: float):
    ...

@property
def width_relative(self) -> float:
    '''Gets or sets the value that represents the percentage of shape's relative width.'''
    ...

@width_relative.setter
def width_relative(self, value: float):
    ...

New public properties left_relative and top_relative for specifying the shape relative position in percent have been added to the Shape class:

@property
def left_relative(self) -> float:
    '''Gets or sets the value that represents shape's relative left position in percent.'''
    ...

@left_relative.setter
def left_relative(self, value: float):
    ...

@property
def top_relative(self) -> float:
    '''Gets or sets the value that represents shape's relative top position in percent.'''
    ...

@top_relative.setter
def top_relative(self, value: float):
    ...

New public enums RelativeHorizontalSize and RelativeVerticalSize have been introduced:

class RelativeHorizontalSize:
    '''Specifies relatively to what the width of a shape or a text frame is calculated horizontally.'''

class RelativeVerticalPosition:
    '''Specifies to what the vertical position of a shape or text frame is relative.'''
from aspose.words import Document, DocumentBuilder
from aspose.words.drawing import ShapeType, RelativeHorizontalSize, WrapType, RelativeVerticalSize, \
    RelativeVerticalPosition, RelativeHorizontalPosition

doc = Document()
builder = DocumentBuilder(doc)

# Adding a simple shape with absolute size and position.
shape = builder.insert_shape(ShapeType.RECTANGLE, 100, 40)
# Set WrapType to WrapType.None since Inline shapes are automatically converted to absolute units.
shape.wrap_type = WrapType.NONE

# Checking and setting the relative horizontal size.
if shape.relative_horizontal_size == RelativeHorizontalSize.DEFAULT:
    # Setting the horizontal size binding to Margin.
    shape.relative_horizontal_size = RelativeHorizontalSize.MARGIN
    # Setting the width to 50 % of Margin width.
    shape.width_relative = 50

# Checking and setting the relative vertical size.
if shape.relative_vertical_size == RelativeVerticalSize.DEFAULT:
    # Setting the vertical size binding to Margin.
    shape.relative_vertical_size = RelativeVerticalSize.MARGIN
    # Setting the height to 30 % of Margin height.
    shape.height_relative = 30

# Checking and setting the relative vertical position.
if shape.relative_vertical_position == RelativeVerticalPosition.PARAGRAPH:
    # Setting the position binding to top margin.
    shape.relative_vertical_position = RelativeVerticalPosition.TOP_MARGIN
    # Setting relative Top to 30 % of top margin position.
    shape.top_relative = 30

# Checking and setting the relative horizontal position.
if shape.relative_horizontal_position == RelativeHorizontalPosition.DEFAULT:
    # Setting the position binding to right margin.
    shape.relative_horizontal_position = RelativeHorizontalPosition.RIGHT_MARGIN
    # The position relative value can be negative.
    shape.left_relative = -260

doc.save("output.docx")

Removed obsolete property JsonDataLoadOptions.ExactDateTimeParseFormat

The obsolete property JsonDataLoadOptions.exact_date_time_parse_format has been removed. Please use the JsonDataLoadOptions.exact_date_time_parse_formats property instead.

@property
def exact_date_time_parse_formats(self) -> Iterable[str]:
    '''Gets or sets exact formats for parsing JSON date-time values while loading JSON. The default is ``None``.
    
    Strings encoded using Microsoft® JSON date-time format (for example, "/Date(1224043200000)/") are always
    recognized as date-time values regardless of a value of this property. The property defines additional
    formats to be used while parsing date-time values from strings in the following way:
    
    * When :attr:`JsonDataLoadOptions.exact_date_time_parse_formats` is ``None``, the ISO-8601 format and all date-time formats
      supported for the current, English USA, and English New Zealand cultures are used additionally in
      the mentioned order.
    
    * When :attr:`JsonDataLoadOptions.exact_date_time_parse_formats` contains strings, they are used as additional date-time
      formats utilizing the current culture.
    
    * When :attr:`JsonDataLoadOptions.exact_date_time_parse_formats` is empty, no additional date-time formats are used.'''
    ...
from aspose.words.reporting import JsonDataSource, JsonDataLoadOptions

options = JsonDataLoadOptions()
options.exact_date_time_parse_formats = ["dd.MM.yy"]

dataSource = JsonDataSource(stream, options)