Archive

How To Color a Group of Objects Using xlwings?

Example

Code

import xlwings as xw
import os

def set_style(cht):
    cht.ChartArea.Format.Line.Visible=False
    cht.PlotArea.Format.Fill.Visible=False
    cht.PlotArea.Format.Line.Visible=True
    cht.PlotArea.Format.Line.ForeColor.RGB=xw.utils.rgb_to_int((200,200,200))
    #cht.PlotArea.Format.Line.ForeColor.ObjectThemeColor = msoThemeColorText1
    ax1=cht.Axes(1)
    ax2=cht.Axes(2)
    ax1.HasTitle=True
    ax1.AxisTitle.Text='Categories'
    ax1.AxisTitle.Font.Size=10
    ax1.TickLabels.Font.Size=8
    #ax1.TickLabels.NumberFormat='0.00'
    ax1.HasMajorGridlines=False
    ax2.HasTitle=True
    ax2.AxisTitle.Text='Values'
    ax2.AxisTitle.Font.Size=10
    ax2.TickLabels.Font.Size=8
    ax2.HasMajorGridlines=False
    cht.HasTitle=True
    #cht.ChartTitle.Caption='Plot'
    #cht.ChartTitle.Font.Size=12

root=os.getcwd()
app=xw.App(visible=True,add_book=False)
wb=app.books.open(root+r'/data.xlsx',read_only=False)
sht=wb.sheets('Sheet1')

sht.api.Range('A1:B4').Select()
shp=sht.api.Shapes.AddChart2(-1,xw.constants.ChartType.xlColumnClustered,20,20,350,250,True)
cht=shp.Chart

cht.ChartGroups(1).GapWidth=100
  
colors=[[51,51,0],
        [102,102,0],
        [153,153,0],
        [204,204,0]]
for i in range(4):
    cht.SeriesCollection(1).Points(i+1).Format.Fill.ForeColor.RGB \
    = xw.utils.rgb_to_int((colors[i][0],colors[i][1],colors[i][2]))

set_style(cht)

#wb.save()
#app.kill()

How to use Application.Caller in the xlwings API way

The Application.Caller property in Excel’s object model is a powerful tool for identifying the cell or range that initiated a specific action, such as a macro or a user-defined function (UDF). In xlwings, this property is accessed through the api property of the Application object, allowing Python scripts to interact with Excel in a manner similar to VBA. This functionality is particularly useful for creating dynamic and responsive Excel applications where the script’s behavior depends on the location from which it was called.

Functionality:
Application.Caller returns a Range object representing the cell that called the macro or function. This is essential for UDFs where the function needs to know its own location in the worksheet to perform context-specific calculations or to retrieve adjacent cell values. It can also be used in event-driven macros to determine the source of a trigger.

Syntax in xlwings:
The property is accessed via:

caller_range = xw.apps[0].api.Caller
# or, if you have a specific app or workbook context:
# caller_range = app.api.Caller
# caller_range = book.app.api.Caller

The returned object is a Range from the Excel object model, which xlwings wraps. You can then use its properties and methods, such as Address, Row, Column, or Value.

Parameters:
Application.Caller does not take any parameters. Its return value depends on the context:

  • If called from a worksheet function (UDF), it returns the cell containing the function.
  • If called from a shape (like a button) assigned to a macro, it returns the shape name as a string.
  • If called from a chart or in an unsupported context, it may return an error or None.

Example Usage:

  1. In a User-Defined Function (UDF): A UDF that sums the values of the cell to its left and right, using the caller’s position.
import xlwings as xw

@xw.func
def sum_adjacent():
caller = xw.apps[0].api.Caller
left_cell = caller.Offset(0, -1).Value
right_cell = caller.Offset(0, 1).Value
# Handle None values (empty cells)
left = left_cell if left_cell is not None else 0
right = right_cell if right_cell is not None else 0
return left + right

When this function is entered in cell B2, it will sum the values in A2 and C2.

  1. In a Macro Triggered by a Button: A script that changes the color of the button’s adjacent cell.
import xlwings as xw

def button_macro():
caller = xw.apps[0].api.Caller
# Assuming caller is a shape name (button), get its top-left cell
# This requires additional logic to map shape to cell, often via TopLeftCell
if isinstance(caller, str): # It's a shape name
    shape = xw.books[0].sheets[0].shapes[caller]
    target_cell = shape.TopLeftCell
    target_cell.color = (255, 0, 0) # Red fill
else: # It's a Range
    caller.color = (255, 0, 0)

How To Create Contour Plot and Filled Contour Plot Using xlwings?

Example

Code

import xlwings as xw
import os

def set_style(cht):
    cht.ChartArea.Format.Line.Visible=False
    cht.PlotArea.Format.Fill.Visible = False
    cht.PlotArea.Format.Line.Visible = False
    cht.PlotArea.Format.Line.ForeColor.RGB=xw.utils.rgb_to_int((200,200,200))
    #cht.PlotArea.Format.Line.ForeColor.ObjectThemeColor = msoThemeColorText1
    ax1 = cht.Axes(1)
    ax2 = cht.Axes(2)
    ax1.HasTitle = True
    ax1.AxisTitle.Text = 'Values 1'
    ax1.AxisTitle.Font.Size = 10
    ax1.TickLabels.Font.Size = 8
    #ax1.TickLabels.NumberFormat = '0.00'
    ax1.HasMajorGridlines = True
    ax2.HasTitle = True
    ax2.AxisTitle.Text = 'Values 2'
    ax2.AxisTitle.Font.Size = 10
    ax2.TickLabels.Font.Size = 8
    ax2.HasMajorGridlines = True
    cht.HasTitle = True
    #cht.ChartTitle.Caption = 'Plot'
    #cht.ChartTitle.Font.Size = 12


root=os.getcwd()
app=xw.App(visible=True,add_book=False)
wb=app.books.open(root+r'/data.xlsx',read_only=False)
sht=wb.sheets('Sheet1')

sht.api.Range('A1:CW100').Select()  #
shp=sht.api.Shapes.AddChart2(-1,xw.constants.ChartType.xlSurfaceTopView,20,20,300,300,True)
cht=shp.Chart  #

set_style(cht)

cht.Export(root+'/cht.jpg')
cht.Export(root+'/cht.svg')
cht.ExportAsFixedFormat(0,root+'/cht.pdf')

#wb.save()
#app.kill()

How to use Application.CalculationVersion in the xlwings API way

The Application.CalculationVersion property in Excel is a read-only property that returns a Long value representing the version of the calculation engine used by Excel. This value is primarily used internally by Excel to track changes in calculation logic, such as after updates to functions or calculation methods. It can be useful for advanced troubleshooting, auditing, or when you need to ensure that a workbook’s calculations are consistent with a specific version of Excel’s calculation engine. In xlwings, you can access this property through the Application object.

Syntax in xlwings:

app.calculation_version
  • app: This is an instance of the xlwings App class, representing the Excel application. You typically obtain it by app = xw.apps.active or by creating a new instance.
  • calculation_version: This property returns an integer (Long) that encodes the calculation version. The value is composed of two parts: the major version (higher 16 bits) and the minor version (lower 16 bits). For example, a value of 196617 might correspond to version 3.9 (where 3 is the major part and 9 is the minor part, but exact mapping depends on Excel’s internal use).

Example Usage:
Here are a few code examples demonstrating how to use calculation_version with xlwings:

  1. Retrieving the Calculation Version:
    This example gets the calculation version from the active Excel application and prints it as a decimal number and as separate major/minor components using bitwise operations.
import xlwings as xw

# Connect to the active Excel application
app = xw.apps.active

# Get the calculation version
version = app.calculation_version
print(f"Calculation Version (decimal): {version}")

# Extract major and minor parts (higher 16 bits and lower 16 bits)
major_version = (version >> 16) & 0xFFFF
minor_version = version & 0xFFFF
print(f"Major Version: {major_version}, Minor Version: {minor_version}")
  1. Comparing Calculation Versions:
    You can compare the calculation version to a known value to check for compatibility or changes. For instance, you might want to verify if the version matches a specific release.
import xlwings as xw

app = xw.apps.active
current_version = app.calculation_version
target_version = 196617 # Example target version, adjust based on your needs

if current_version == target_version:
    print("Calculation engine is up-to-date with the target version.")
else:
    print(f"Calculation version differs. Current: {current_version}, Target: {target_version}")
  1. Logging Calculation Version for Auditing:
    In scenarios where you need to audit workbook calculations, you can log the calculation version along with other details to ensure reproducibility.
import xlwings as xw
import datetime

app = xw.apps.active
version = app.calculation_version
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")

# Log to a file or print
log_entry = f"{timestamp} - Calculation Version: {version}\n"
with open("calculation_log.txt", "a") as log_file:
log_file.write(log_entry)
print("Calculation version logged successfully.")

Notes:

  • The exact meaning of the version number is not publicly documented by Microsoft and may change with Excel updates. It is generally used for internal tracking, so rely on it cautiously.
  • This property is available in Excel 2007 and later versions. In xlwings, ensure you have a compatible Excel installation.
  • Since calculation_version is read-only, you cannot set it directly; it reflects the current state of Excel’s calculation engine.

How To Set Surface Color, Transparency, and Lighting Using xlwings?

Example

Code

import xlwings as xw
import os

def set_style(cht):
    cht.ChartArea.Format.Line.Visible=False
    cht.PlotArea.Format.Fill.Visible = False
    cht.PlotArea.Format.Line.Visible = False
    cht.PlotArea.Format.Line.ForeColor.RGB=xw.utils.rgb_to_int((200,200,200))
    #cht.PlotArea.Format.Line.ForeColor.ObjectThemeColor = msoThemeColorText1
    ax1 = cht.Axes(1)
    ax2 = cht.Axes(2)
    ax1.HasTitle = True
    ax1.AxisTitle.Text = 'Values 1'
    ax1.AxisTitle.Font.Size = 10
    ax1.TickLabels.Font.Size = 8
    #ax1.TickLabels.NumberFormat = '0.00'
    ax1.HasMajorGridlines = True
    ax2.HasTitle = True
    ax2.AxisTitle.Text = 'Values 2'
    ax2.AxisTitle.Font.Size = 10
    ax2.TickLabels.Font.Size = 8
    ax2.HasMajorGridlines = True
    cht.HasTitle = True
    #cht.ChartTitle.Caption = 'Plot'
    #cht.ChartTitle.Font.Size = 12


root=os.getcwd()
app=xw.App(visible=True,add_book=False)
wb=app.books.open(root+r'/data.xlsx',read_only=False)
sht=wb.sheets('Sheet1')

sht.api.Range('A1:CW100').Select()  #
shp=sht.api.Shapes.AddChart2(-1,xw.constants.ChartType.xlSurface,20,20,300,300,True)
cht=shp.Chart  #
n=cht.SeriesCollection().Count
for i in range(n):
    fl=cht.SeriesCollection(i+1).Format.Fill
    fl.Visible=True
    fl.ForeColor.RGB=xw.utils.rgb_to_int((255,128,0))
    fl.ForeColor.Brightness=0.2
    fl.Transparency=0.3

set_style(cht)
cht.HasLegend=False

cht.Export(root+'/cht.jpg')
cht.Export(root+'/cht.svg')
cht.ExportAsFixedFormat(0,root+'/cht.pdf')

#wb.save()
#app.kill()

How to use Application.CalculationState in the xlwings API way

The CalculationState property of the Application object in Excel’s object model is accessible through the xlwings library, providing insight into the current calculation status of Excel. This property is particularly useful when automating tasks that depend on whether Excel is actively calculating formulas, has completed calculations, or is in a state where calculations are pending. By monitoring the CalculationState, developers can write more robust and efficient automation scripts that wait for calculations to finish before proceeding, thereby avoiding errors or incorrect data processing due to incomplete calculations.

Functionality:
The CalculationState property returns an integer value indicating the calculation state of Excel. It helps determine if Excel is busy calculating, done, or in another calculation-related state. This is essential in scenarios where subsequent operations, such as reading calculated cell values or saving workbooks, should only occur after all formulas have been recalculated. In xlwings, this property is accessed via the Application object, allowing Python scripts to interact with Excel’s calculation engine programmatically.

Syntax:
In xlwings, the CalculationState property is called on the app object, which represents the Excel application. The syntax is straightforward:

state = app.api.CalculationState

Here, app is an instance of the xlwings App class (e.g., created with app = xw.App() or xw.apps.active), and .api provides direct access to the underlying Excel object model. The CalculationState property does not take any parameters and returns an integer. The return values correspond to specific states, as defined in the Excel object model. Commonly used values include:

  • -4135 (or xlwings.constants.CalculationState.xlDone): Indicates that calculations are complete.
  • -4134 (or xlwings.constants.CalculationState.xlCalculating): Indicates that calculations are in progress.
  • -4133 (or xlwings.constants.CalculationState.xlPending): Indicates that calculations are pending, meaning some formulas need to be recalculated but Excel hasn’t started yet.

For clarity, xlwings provides constants in the xlwings.constants module, though they are not always required if using the raw integer values. Developers can refer to the Excel VBA documentation for a full list, but these three states are the most relevant for typical automation tasks.

Examples:
Below are practical xlwings API code examples demonstrating how to use the CalculationState property in Python scripts.

  1. Checking if Excel is currently calculating:
    This example waits for Excel to finish all calculations before proceeding, which is useful when working with workbooks that have complex formulas.
import xlwings as xw
import time

# Connect to the active Excel application
app = xw.apps.active

# Perform an action that triggers calculation, e.g., changing a cell value
wb = app.books.active
wb.sheets[0].range("A1").value = 10 # This might trigger recalculation

# Wait until calculations are complete
while app.api.CalculationState == -4134: # xlCalculating
time.sleep(0.1) # Pause briefly to avoid high CPU usage
print("Calculations finished. Safe to proceed.")
  1. Monitoring calculation state during a long operation:
    In this example, the script logs the calculation state while a large dataset is being processed, helping to debug or optimize performance.
import xlwings as xw

app = xw.App(visible=True) # Start a new Excel instance
wb = app.books.add()
sheet = wb.sheets[0]

# Fill a range with formulas to simulate a heavy calculation load
for i in range(1, 101):
    sheet.range(f"A{i}").formula = f"=RAND()*{i}"

# Force a full calculation
app.api.Calculate()

# Check and print the calculation state
state = app.api.CalculationState
if state == -4134:
    print("Excel is currently calculating formulas.")
elif state == -4135:
    print("Excel has finished all calculations.")
elif state == -4133:
    print("Calculations are pending.")
else:
    print(f"Unknown calculation state: {state}")

# Clean up
wb.close()
app.quit()
  1. Using constants for better readability:
    While xlwings doesn’t have built-in enums for all Excel constants, developers can define their own or use the ones available. This example shows how to use constants to make the code more maintainable.
import xlwings as xw

# Define constants based on Excel's object model (or import from xlwings.constants if available)
xlCalculating = -4134
xlDone = -4135
xlPending = -4133

app = xw.apps.active
state = app.api.CalculationState

if state == xlCalculating:
print("Wait for calculations to complete.")
elif state == xlDone:
print("Proceed with data extraction.")
else:
print("Check for pending calculations.")

How To Create Surface Models Using xlwings?

Example

Code

import xlwings as xw
import os

def set_style(cht):
    cht.ChartArea.Format.Line.Visible=False
    cht.PlotArea.Format.Fill.Visible = False
    cht.PlotArea.Format.Line.Visible = False
    cht.PlotArea.Format.Line.ForeColor.RGB=xw.utils.rgb_to_int((200,200,200))
    #cht.PlotArea.Format.Line.ForeColor.ObjectThemeColor = msoThemeColorText1
    ax1 = cht.Axes(1)
    ax2 = cht.Axes(2)
    ax1.HasTitle = True
    ax1.AxisTitle.Text = 'Values 1'
    ax1.AxisTitle.Font.Size = 10
    ax1.TickLabels.Font.Size = 8
    #ax1.TickLabels.NumberFormat = '0.00'
    ax1.HasMajorGridlines = True
    ax2.HasTitle = True
    ax2.AxisTitle.Text = 'Values 2'
    ax2.AxisTitle.Font.Size = 10
    ax2.TickLabels.Font.Size = 8
    ax2.HasMajorGridlines = True
    cht.HasTitle = True
    #cht.ChartTitle.Caption = 'Plot'
    #cht.ChartTitle.Font.Size = 12


root=os.getcwd()
app=xw.App(visible=True,add_book=False)
wb=app.books.open(root+r'/data.xlsx',read_only=False)
sht=wb.sheets('Sheet1')

sht.api.Range('A1:CW100').Select()  #
shp=sht.api.Shapes.AddChart2(-1,xw.constants.ChartType.xlSurfaceWireframe,20,20,300,300,True)
cht=shp.Chart  #

set_style(cht)

cht.Export(root+'/cht.jpg')
cht.Export(root+'/cht.svg')
cht.ExportAsFixedFormat(0,root+'/cht.pdf')

#wb.save()
#app.kill()

How to use Application.CalculationInterruptKey in the xlwings API way

The Application.CalculationInterruptKey property in Excel is a member that allows developers to control which key can be used to interrupt a long calculation in Excel. This is particularly useful when running complex or lengthy calculations where you might want to provide a way to stop the process without forcing Excel to become unresponsive. In xlwings, this property can be accessed and modified through the Application object, providing a programmatic way to manage calculation interruptions in automated Excel tasks.

Functionality:
The CalculationInterruptKey property determines the key that, when pressed during a calculation, will interrupt the process. It helps in creating more user-friendly or controlled environments by specifying whether interruptions are allowed and which key triggers them. This can prevent accidental interruptions or allow for deliberate stops in scenarios like data processing macros.

Syntax in xlwings:
In xlwings, you can access this property using the api property of the App or Book objects to reach the underlying Excel Application object. The syntax is as follows:

app = xw.apps.active # Get the active Excel application
interrupt_key = app.api.CalculationInterruptKey

To set the property, assign a value from the XlCalculationInterruptKey enumeration. The available options are:

  • xlAnyKey (1): Any key press will interrupt the calculation.
  • xlEscKey (2): Only the Esc key will interrupt the calculation.
  • xlNoKey (3): No key will interrupt the calculation; this disables interruptions.

Parameters and Values:
The property accepts integer values corresponding to the enumeration. In xlwings, you can use the constants directly if imported, but typically, you can use the integer values for simplicity. For example:

  • Use 1 for xlAnyKey.
  • Use 2 for xlEscKey.
  • Use 3 for xlNoKey.

Example Usage:
Here is a code example demonstrating how to set and retrieve the CalculationInterruptKey property using xlwings:

import xlwings as xw

# Connect to the active Excel application
app = xw.apps.active

# Get the current interrupt key setting
current_key = app.api.CalculationInterruptKey
print(f"Current interrupt key setting: {current_key}") # Output might be 2 for xlEscKey

# Set the interrupt key to xlAnyKey (any key press interrupts)
app.api.CalculationInterruptKey = 1 # Equivalent to xlAnyKey
print("Interrupt key set to xlAnyKey.")

# Perform a long calculation (e.g., a loop that simulates work)
# In a real scenario, this could be a heavy Excel calculation.
try:
    # Simulate a calculation that might be interrupted
    for i in range(1000000):
        # Some calculation code here
        if i % 100000 == 0:
            print(f"Processing... {i}")
except KeyboardInterrupt:
    print("Calculation was interrupted by user.")

# Reset to xlEscKey for standard behavior
app.api.CalculationInterruptKey = 2
print("Interrupt key reset to xlEscKey.")

How To Create Surface + 3D Filled Contour Plot Using xlwings?

Example

Code

import xlwings as xw
import os

def set_style(cht):
    cht.ChartArea.Format.Line.Visible=False
    cht.PlotArea.Format.Fill.Visible = False
    cht.PlotArea.Format.Line.Visible = False
    cht.PlotArea.Format.Line.ForeColor.RGB=xw.utils.rgb_to_int((200,200,200))
    #cht.PlotArea.Format.Line.ForeColor.ObjectThemeColor = msoThemeColorText1
    ax1 = cht.Axes(1)
    ax2 = cht.Axes(2)
    ax1.HasTitle = True
    ax1.AxisTitle.Text = 'Values 1'
    ax1.AxisTitle.Font.Size = 10
    ax1.TickLabels.Font.Size = 8
    #ax1.TickLabels.NumberFormat = '0.00'
    ax1.HasMajorGridlines = True
    ax2.HasTitle = True
    ax2.AxisTitle.Text = 'Values 2'
    ax2.AxisTitle.Font.Size = 10
    ax2.TickLabels.Font.Size = 8
    ax2.HasMajorGridlines = True
    cht.HasTitle = True
    #cht.ChartTitle.Caption = 'Plot'
    #cht.ChartTitle.Font.Size = 12


root=os.getcwd()
app=xw.App(visible=True,add_book=False)
wb=app.books.open(root+r'/data.xlsx',read_only=False)
sht=wb.sheets('Sheet1')

sht.api.Range('A1:CW100').Select()  #
shp=sht.api.Shapes.AddChart2(-1,xw.constants.ChartType.xlSurface,20,20,300,300,True)
cht=shp.Chart  #

set_style(cht)

cht.Export(root+'/cht.jpg')
cht.Export(root+'/cht.svg')
cht.ExportAsFixedFormat(0,root+'/cht.pdf')

#wb.save()
#app.kill()

How to use Application.Calculation in the xlwings API way

The Application.Calculation property in Excel is a crucial setting that determines how formulas are recalculated within a workbook. In xlwings, this property allows you to control the calculation mode programmatically, which is essential for optimizing performance, especially when dealing with large or complex spreadsheets that involve numerous formulas and dependencies.

Functionality
This property controls the Excel calculation engine’s mode. You can set it to force automatic recalculation, manual recalculation, or a semi-automatic mode. This is particularly useful when you are writing data to many cells via xlwings and want to prevent Excel from recalculating after each write operation, which can significantly slow down execution. By setting calculation to manual, performing all data updates, and then setting it back to automatic (or triggering a manual calculation), you can drastically improve the performance of your scripts.

Syntax and Parameters
In xlwings, you access this property through the app object, which represents the Excel Application. The syntax is straightforward:
app.calculation
This property is both gettable and settable. When setting it, you assign one of the following constants, which are available directly in xlwings:

Constant (from xlwings.constants)ValueDescription
xlwings.constants.Calculation.xlCalculationAutomatic-4105Excel controls recalculation.
xlwings.constants.Calculation.xlCalculationManual-4135Recalculation only occurs when explicitly requested (e.g., by pressing F9).
xlwings.constants.Calculation.xlCalculationSemiautomatic2Recalculation is automatic except for data tables.

You can also use the raw numeric values, but using the named constants is recommended for better code readability.

Code Examples
Here are practical examples of using the app.calculation property with xlwings:

  1. Checking the Current Calculation Mode:
import xlwings as xw
app = xw.apps.active # Get the active Excel application
current_mode = app.calculation
print(f"Current calculation mode is: {current_mode}")
  1. Setting Calculation to Manual for Performance:
    This is a common pattern for batch operations.
import xlwings as xw
from xlwings.constants import Calculation

app = xw.apps.active
original_mode = app.calculation # Save the original state

# Set to manual to prevent recalculations during data writes
app.calculation = Calculation.xlCalculationManual

# Perform your data operations (e.g., writing to many cells)
wb = app.books.active
sht = wb.sheets[0]
for row in range(2, 1002):
    sht.range(f'A{row}').value = row * 10
    # Without manual calculation, Excel would recalculate here 1000 times!

# After data is written, trigger a single full calculation
wb.app.calculate() # Equivalent to pressing F9 in Excel

# Restore the original calculation mode
app.calculation = original_mode
  1. Setting Calculation to Automatic:
import xlwings as xw
from xlwings.constants import Calculation

app = xw.apps.active
app.calculation = Calculation.xlCalculationAutomatic
print("Calculation set to Automatic.")