Purpose
Calling a Python function from GuiXT

Solution
Wrap the Python function call in a VB function and call it using CallVB and Python.NET

Example
Wrap your Python function calls in a VB Program.
When creating the VB wrapper, Python.NET must be imported.

After wrapping, the Python functions can be called from GuiXT.


GuiXT Script:

GuiXT
// set some demo values
Set V[region.1] "Americas"
Set V[sales.1] "2584"

Set V[region.2] "Europe"
Set V[sales.2] "1228"

Set V[region.3] "Asia"
Set V[sales.3] "1628"

CallVB result = vbcall.ExcelWriter.WriteExcel 3


VB Wrapper:

VB.NET
Imports Python.Runtime
Imports guinet
Imports System.Threading

Public Class ExcelWriter
    Public Function WriteExcel(ByVal rows As Integer) As String
        Dim result As String = String.Empty
        Dim thread As New Thread(
            Sub()
                Try
                    ' Initialize Python runtime and acquire GIL
                    Runtime.PythonDLL = "C:\Python312\python312.dll"
                    PythonEngine.Initialize()
                    Using Py.GIL()
                        Try
                            Dim guixt As New guinet.guixt
                            Dim csvData As New System.Text.StringBuilder()

                            ' Build CSV data
                            For k As Integer = 1 To rows
                                Dim region As String = guixt.GetVariable(
                                    "region." & k
                                )
                                Dim sales As String = guixt.GetVariable(
                                    "sales." & k
                                )
                                csvData.Append(region & "," & sales & ",")
                            Next

                            ' Remove trailing comma
                            If csvData.Length > 0 Then
                                csvData.Length -= 1
                            End If

                            ' Import and call Python function
                            ' Ensure that write_excel.py is in the Python path
                            ' or in the working directory
                            Dim pyModule As PyObject = Py.Import("write_excel")
                            result = pyModule.InvokeMethod(
                                "write_data_to_excel",
                                New PyObject() {
                                    New PyString(csvData.ToString()),
                                    New PyString("output.xlsx")
                                }
                            ).ToString()
                        Catch ex As Exception
                            result = "Error in Python call: " & ex.Message
                        End Try
                    End Using
                Catch ex As Exception
                    result = "Error initializing Python: " & ex.Message
                Finally
                    ' Shutdown Python runtime
                    If PythonEngine.IsInitialized Then
                        PythonEngine.Shutdown()
                    End If
                End Try
            End Sub)

        ' Set the thread to STA (Single Threaded Apartment)
        ' This is necessary to ensure the wrapper runs in one single thread
        ' Python.GIL must be acquired and stopped in the same thread where
        ' PythonEngine.Initialize() is called
        ' Otherwise, your application may crash
        thread.SetApartmentState(ApartmentState.STA)
        thread.Start()
        thread.Join() ' Wait for the thread to complete

        Return result
    End Function
End Class


Python Script:

Python
from openpyxl import Workbook

def write_data_to_excel(csv_data, output_path="output.xlsx"):
    values = csv_data.split(',')
    data = [
        {
            'region': values[i], 'sales': values[i+1]
            } for i in range(0, len(values), 2)
        ]

    wb = Workbook()
    ws = wb.active
    
    ws.column_dimensions['A'].width = 30
    ws.column_dimensions['B'].width = 20
    
    for k, row in enumerate(data, start=1):
        ws.cell(row=k, column=1, value=row['region'])
        ws.cell(row=k, column=2, value=row['sales'])
    wb.save(output_path)

Components InputAssistant + Controls