We are excited to announce the release of Spire.Office for Python 11.7.0. This version introduces several powerful enhancements: Spire.Doc supports configuring a license via environment variables, Spire.XLS adds support for Data Simulation Analysis, Slicers, and Excel to JSON conversion, Spire.PDF supports auto-fitting text in signature fields, and Spire.Presentation supports configuring licenses via environment variables.
Moreover, many known issues that occurred when converting, processing, and saving Word/Excel/PDF/PowerPoint files have been successfully fixed. More details are listed below.
Click the link to download Spire.Office for Python 11.7.0:
Here is a list of changes made in this release
Spire.Doc for Python
| Category | ID | Description |
| New Feature | - | Spire.Doc now automatically detects and loads license information from the following environment variables:
SPIRE_OFFICE_LICENSE_KEY SPIRE_DOC_LICENSE_KEY SPIRE_LICENSE_KEY |
Spire.XLS for Python
| Category | ID | Description |
| New Feature | SPIREXLS-6020 | Added support for Data Simulation Analysis (Scenario Manager), including creation, editing, deletion, summary generation, and merging.
wb = Workbook()
wb.LoadFromFile(inputFile)
worksheet = wb.Worksheets[0]
scenarios = worksheet.Scenarios
currentChangePercentage_Values = [0.23, 0.8, 1.1, 0.5, 0.35, 0.2]
increasedChangePercentage_Values = [0.45, 0.56, 0.9, 0.5, 0.58, 0.43]
decreasedChangePercentage_Values = [0.3, 0.2, 0.5, 0.3, 0.5, 0.23]
currentQuantity_Values = [1500, 3000, 5000, 4000, 500, 4000]
increasedQuantity_Values = [1000, 5000, 4500, 3900, 10000, 8900]
decreasedQuantity_Values = [1000, 2000, 3000, 3000, 300, 4000]
scenarios.Add("Current % of Change", worksheet.Range["F5:F10"], currentChangePercentage_Values)
scenarios.Add("Increased % of Change", worksheet.Range["F5:F10"], increasedChangePercentage_Values)
scenarios.Add("Decreased % of Change", worksheet.Range["F5:F10"], decreasedChangePercentage_Values)
scenarios.Add("Current Quantity", worksheet.Range["D5:D10"], currentQuantity_Values)
scenarios.Add("Increased Quantity", worksheet.Range["D5:D10"], increasedQuantity_Values)
scenarios.Add("Decreased Quantity", worksheet.Range["D5:D10"], decreasedQuantity_Values)
wb.SaveToFile(outputFile, ExcelVersion.Version2013)
wb.Dispose()
wb = Workbook()
wb.LoadFromFile(inputFile)
worksheet = wb.Worksheets[0]
scenarios = worksheet.Scenarios
currentChangePercentage_Values = [0.23, 0.8, 1.1, 0.5, 0.35, 0.2]
increasedChangePercentage_Values = [0.45, 0.56, 0.9, 0.5, 0.58, 0.43]
decreasedChangePercentage_Values = [0.3, 0.2, 0.5, 0.3, 0.5, 0.23]
currentQuantity_Values = [1500, 3000, 5000, 4000, 500, 4000]
increasedQuantity_Values = [1000, 5000, 4500, 3900, 10000, 8900]
decreasedQuantity_Values = [1000, 2000, 3000, 3000, 300, 4000]
scenarios.Add("Current % of Change", worksheet.Range["F5:F10"], currentChangePercentage_Values)
scenarios.Add("Increased % of Change", worksheet.Range["F5:F10"], increasedChangePercentage_Values)
scenarios.Add("Decreased % of Change", worksheet.Range["F5:F10"], decreasedChangePercentage_Values)
scenarios.Add("Current Quantity", worksheet.Range["D5:D10"], currentQuantity_Values)
scenarios.Add("Increased Quantity", worksheet.Range["D5:D10"], increasedQuantity_Values)
scenarios.Add("Decreased Quantity", worksheet.Range["D5:D10"], decreasedQuantity_Values)
worksheet.Scenarios.Summary(worksheet.Range["L7"])
wb.SaveToFile(outputFile, ExcelVersion.Version2013)
wb.Dispose()
wb = Workbook()
wb.LoadFromFile(inputFile)
worksheet = wb.Worksheets[0]
scenarios = worksheet.Scenarios
scenario1 = scenarios[0]
scenario2 = scenarios[1]
scenario1.SetVariableCells(worksheet.Range["A1:A5"], scenario2.Values)
sourceCell = worksheet.Range["B1:B5"]
scenario2.SetVariableCells(sourceCell, scenario2.Values)
scenario1.Show()
scenario2.Show()
self.get_content(scenario1, outputFile_TXT)
wb.SaveToFile(outputFile, ExcelVersion.Version2013)
wb.Dispose()
wb = Workbook()
wb.LoadFromFile(inputFile)
worksheet = wb.Worksheets[0]
scenarios = worksheet.Scenarios
scenarios.RemoveScenarioAt(0)
scenarios.RemoveScenarioByName("two")
content = ""
content += "Count:" + str(scenarios.Count) + "\n"
content += "ContainsScenario:" + str(scenarios.ContainsScenario("two")) + "\n"
content += "ContainsScenario:" + str(scenarios.ContainsScenario("one")) + "\n"
with open(outputFile, 'w') as f:
f.write(content)
wb.Dispose()
wb = Workbook()
wb.LoadFromFile(inputFile)
worksheet = wb.Worksheets[0]
scenarios = worksheet.Scenarios
scenarios.RemoveScenarioAt(0)
scenarios.RemoveScenarioByName("two")
content = ""
content += "Count:" + str(scenarios.Count) + "\n"
content += "ContainsScenario:" + str(scenarios.ContainsScenario("two")) + "\n"
content += "ContainsScenario:" + str(scenarios.ContainsScenario("one")) + "\n"
with open(outputFile, 'w') as f:
f.write(content)
wb.Dispose()
|
| New Feature | - | Added support for adding Slicers using table data.
wb = Workbook()
wb.LoadFromFile(inputFile)
worksheet = wb.Worksheets[0]
slicers = worksheet.Slicers
table = worksheet.ListObjects.Create("Super Table", worksheet.Range["A1:C9"])
count = 3
for type in SlicerStyleType.dict.values():
if isinstance(type, SlicerStyleType):
count += 5
rangeStr = "E" + str(count)
index = slicers.Add(table, rangeStr, 0)
xlsSlicer = slicers[index]
xlsSlicer.Name = "slicers_" + str(count)
xlsSlicer.StyleType = type
wb.SaveToFile(outputFile_xlsx, ExcelVersion.Version2013)
wb.Dispose()
|
| New Feature | - | Added support for adding Slicers using PivotTable data.
wb = Workbook() wb.LoadFromFile(inputFile) worksheet = wb.Worksheets[0] pt = sheet.PivotTables[0] slicers = worksheet.Slicers index = slicers.Add(pt, "E12", 0) xlsSlicer = slicers[index] xlsSlicer.Name = "test_xlsSlicer" xlsSlicer.Width = 100 xlsSlicer.Height = 120 xlsSlicer.StyleType = SlicerStyleType.SlicerStyleLight2 xlsSlicer.PositionLocked = True slicerCache = xlsSlicer.SlicerCache slicerCache.CrossFilterType = SlicerCacheCrossFilterType.ShowItemsWithNoData slicerCacheItems = xlsSlicer.SlicerCache.SlicerCacheItems xlsSlicerCacheItem = slicerCacheItems[0] xlsSlicerCacheItem.Selected = False slicers_2 = worksheet.Slicers r1 = pt.PivotFields["year"] index_2 = slicers_2.Add(pt, "I12", r1) xlsSlicer_2 = slicers[index_2] xlsSlicer_2.RowHeight = 40 xlsSlicer_2.StyleType = SlicerStyleType.SlicerStyleLight3 xlsSlicer_2.PositionLocked = False slicerCache_2 = xlsSlicer_2.SlicerCache slicerCache_2.CrossFilterType = SlicerCacheCrossFilterType.ShowItemsWithDataAtTop slicerCacheItems_2 = xlsSlicer_2.SlicerCache.SlicerCacheItems xlsSlicerCacheItem_2 = slicerCacheItems_2[1] xlsSlicerCacheItem_2.Selected = False pt.CalculateData() wb.SaveToFile(outputFile_xlsx, ExcelVersion.Version2013) wb.Dispose() |
| New Feature | - | Added support for removing Slicers.
wb = Workbook() wb.LoadFromFile(inputFile) worksheet_1 = wb.Worksheets[0] slicers = worksheet_1.Slicers slicers.RemoveAt(0) slicer = worksheet_1.Slicers[1] worksheet_1.Slicers.Remove(slicer) worksheet_2 = wb.Worksheets[2] worksheet_2.Slicers.Clear() wb.SaveToFile(outputFile_xlsx, ExcelVersion.Version2013) |
| New Feature | - | Added support for modifying Slicers.
wb = Workbook() wb.LoadFromFile(inputFile) worksheet = wb.Worksheets[0] slicers = worksheet.Slicers xlsSlicer = slicers[0] xlsSlicer.StyleType = SlicerStyleType.SlicerStyleDark4 xlsSlicer.Caption = "Slicer" xlsSlicer.PositionLocked = True slicerCacheItems = xlsSlicer.SlicerCache.SlicerCacheItems xlsSlicerCacheItem = slicerCacheItems[0] xlsSlicerCacheItem.Selected = False displayValue = xlsSlicerCacheItem.DisplayValue slicerCache = xlsSlicer.SlicerCache slicerCache.CrossFilterType = SlicerCacheCrossFilterType.ShowItemsWithNoData wb.SaveToFile(outputFile_xlsx, ExcelVersion.Version2013) |
| New Feature | - | Added support for retrieving Slicer information.
wb = Workbook() wb.LoadFromFile(inputFile) worksheet = wb.Worksheets[0] slicers = worksheet.Slicers content = "" content += "slicers.Count:" + str(slicers.Count) + "\n" xlsSlicer = slicers[1] content += "xlsSlicer.Name:" + xlsSlicer.Name + "\n" content += "xlsSlicer.Caption:" + xlsSlicer.Caption + "\n" content += "xlsSlicer.NumberOfColumns:" + str(xlsSlicer.NumberOfColumns) + "\n" content += "xlsSlicer.ColumnWidth:" + str(xlsSlicer.ColumnWidth) + "\n" content += "xlsSlicer.RowHeight:" + str(xlsSlicer.RowHeight) + "\n" content += "xlsSlicer.ShowCaption:" + str(xlsSlicer.ShowCaption) + "\n" content += "xlsSlicer.PositionLocked:" + str(xlsSlicer.PositionLocked) + "\n" content += "xlsSlicer.Width:" + str(xlsSlicer.Width) + "\n" content += "xlsSlicer.Height:" + str(xlsSlicer.Height) + "\n" slicerCache = xlsSlicer.SlicerCache content += "slicerCache.SourceName:" + slicerCache.SourceName + "\n" content += "slicerCache.IsTabular:" + str(slicerCache.IsTabular) + "\n" content += "slicerCache.Name:" + slicerCache.Name + "\n" slicerCacheItems = slicerCache.SlicerCacheItems xlsSlicerCacheItem = slicerCacheItems[1] content += "xlsSlicerCacheItem.Selected:" + str(xlsSlicerCacheItem.Selected) + "\n" with open(outputFile_T, 'w') as f: f.write(content) wb.Dispose() |
| New Feature | SPIREXLS-6162 | Added support for converting Excel files to JSON data.
workbook = Workbook() workbook.LoadFromFile(inputFile) workbook.SaveToFile(outputFile, FileFormat.Json) workbook.Dispose() |
Spire.Presentation for Python
| Category | ID | Description |
| New Feature | - | Added support for configuring licenses via environment variables, with automatic recognition and loading of the following three variables:
SPIRE_OFFICE_LICENSE_KEY SPIRE_PPT_LICENSE_KEY SPIRE_LICENSE_KEY |
| Optimization | - | Optimized the processing logic of multiple interfaces to further eliminate potential user experience issues. |
| Bug Fix | SPIREPPT-3134 | Fixed an issue where the program threw a "Microsoft PowerPoint 2007 file is corrupt." exception when loading PPTX documents. |
| Bug Fix | SPIREPPT-3135, SPIREPPT-3136 | Fixed an issue where the program threw an "Arg_NullReferenceException" exception when loading PPTX documents. |
Spire.PDF for Python
| Category | ID | Description |
| New Feature | SPIREPDF-7319 | Added the AutoFontSize property to support auto-fitting text content to the size of a signature field.
# Initialize a PDF document object
doc = PdfDocument()
# Load the PDF file that needs to be signed
doc.LoadFromFile(inputFile)
# Specify the password for the PFX certificate file
pfxPassword = "e-iceblue"
# Get the first page of the document
page = doc.Pages.get_Item(0)
# Create an ordinary signature maker using the certificate file
signatureMaker = PdfOrdinarySignatureMaker(doc, inputFile_pfx, pfxPassword)
# Set the signature validation layer (False indicates displaying the validity symbol)
signatureMaker.SetAcro6Layers(False)
# Get the signature object and configure the basic information of the signer
signature = signatureMaker.Signature
signature.Name = "Gary" # Signer's name
signature.ContactInfo = "028-81705109" # Contact information
signature.Location = "Chengdu" # Signature location
signature.Reason = "The certificate of this document" # Reason for signing
# Create a custom signature appearance object
appearance = PdfSignatureAppearance(signature)
appearance.NameLabel = "Signer: " # Name label
appearance.ContactInfoLabel = "ContactInfo: " # Contact information label
appearance.LocationLabel = "Location: " # Location label
appearance.ReasonLabel = "Reaseon: " # Reason label
appearance.SignatureImage = PdfImage.FromFile(inputFile_image) # Load the signature image
appearance.GraphicMode = GraphicMode.SignImageAndSignDetail # Set to display both the signature image and detailed information
signature.DocumentPermissions = PdfCertificationFlags.ForbidChanges # Set document permissions to forbid changes
appearance.SignImageLayout = SignImageLayout.Stretch # Set the layout mode of the signature image to stretch
appearance.AutoFontSize = True # Enable auto font size adjustment for text
# Generate and apply the signature at the specified position on the page (Parameters in order: signature field name, page, X coordinate, Y coordinate, width, height, appearance object)
signatureMaker.MakeSignature("signName", page, 54.0, page.Size.Height - 300.0, 40.0, 40.0, appearance)
# Save the signed PDF document
doc.SaveToFile(outputFile)
# Close the document and release resources
doc.Close()
|
| Bug Fix | SPIREPDF-8056 | Fixed the issue where the font was incorrect after text replacement. |