In INOSIM Modellen ist es sehr praktisch, die Eingabe für Ihre Rezepte in Excel-Tabellen zu organisieren, um entweder einen besseren Überblick über Ihre Eingabe zu haben oder um Parameteränderungen für Personen zugänglich zu machen, die INOSIM nicht kennen. Um die Informationen in Excel innerhalb von INOSIM zu nutzen, können sie in ein Table -Objekt eingelesen werden.
Einführung
Table-Objekte bieten einige Vorteile. Zunächst ist es wesentlich schneller, Ihre Informationen in ein Table-Objekt einzulesen, als auf einzelne Zellen in Excel zuzugreifen. Darüber hinaus sind Table-Objekte in INOSIM indexierte Tabellen. Sie können direkt über den Zeilen- oder Spalten-String-Index (d. h. die Überschrift) auf den Inhalt einer Zelle zugreifen, ohne alle Zeilen oder Spalten mit einer For-Schleife zu durchlaufen. Die nachstehende Tabelle zeigt verschiedene Betriebsparameter für drei Trockner, z. B. die Trocknungsdauer.
Um die Dauer einer Operation in einem Parameter-Steuerelement mit einem Wert aus dem Table-Objekt t_process zu überschreiben, können die Zeilen direkt über den Namen der Teilanlage aufgerufen werden, wenn er mit dem Namen der Teilanlage in der INOSIM Datenbank übereinstimmt. Folgender Code kann verwendet werden:
Sub Drying_Duration(cop As OrderOperation, mop As RecipeOperation)
cop.Duration = t_process(cop.Unit.Name, "Drying [h]") * 3600
End Sub
Read_Table-Funktion
Um diese Daten aus dem Table-Objekt während der Simulation zu lesen, müssen die Daten zunächst aus Excel in das Table-Objekt geschrieben werden. Dies geschieht in der Regel in der Simulation_Init-Prozedur mit der Read_Table-Funktion, die in diesem Tip & Trick eingeführt wird. Um von einer beliebigen Prozedur (z. B. unterschiedliche Parametersteuerungen) auf das Table-Objekt zuzugreifen, muss es als globale Variable deklariert werden, d. h. nicht als lokale Variable in der Simulation_Init.
Die Funktion erwartet folgende Eingabeparameter:
- XLS_Sheet (der Stringname des Excel-Sheets, aus dem Sie lesen möchten),
- VBA_Table (das zuvor definierte Table-Objekt),
- rs und cs (erste Reihe und erste Spalte des Bereichs, aus dem Sie lesen möchten),
- re und ce (letzte Reihe und letzte Spalte, 0 für all),
- ri und ci (Aktivieren des Reihen- und Spaltenindex des Table-Objekts). Wird der Reihenindex aktiviert, wird die erste Reihe als Index benutzt (Spalten entsprechend).
Verwenden Sie zum Beispiel in der Simulation_Init-Prozedur den folgenden Code:
t_input = Read_Table("Input",1,1,0,0,1,1)
Um diese Daten aus dem Table-Objekt während der Simulation zu lesen, müssen die Daten zunächst aus Excel in das Table-Objekt geschrieben werden. Dies geschieht in der Regel in der Simulation_Init-Prozedur mit der Read_Table-Funktion, die in diesem Tip & Trick eingeführt wird. Um von einer beliebigen Prozedur (z.B. unterschiedliche Parametersteuerungen) auf das Table-Objekt zuzugreifen, muss es als globale Variable deklariert werden, d. h. nicht als lokale Variable in der Simulation_Init.
Denken Sie daran: Da keine doppelten Zeilen- oder Spaltenindizes erstellt werden dürfen, darf die als Index verwendete Zeile (oder Spalte) keine doppelten Einträge enthalten. Um die Read_Table -Funktion in Ihrem Projekt zu verwenden, kopieren Sie den folgenden Code in Ihr Makro.
Function Read_Table(XLS_Sheet As String, rs As Integer, cs As Integer, re As Integer, ce As Integer, ri As Boolean, ci As Boolean) As Table
'Support function for reading excel sheets into VBA table objects
'XLS_Sheet = sheet name of excel sheet
'rs and cs = first row(rs)/first column (cs) to be used in sheet
're and ce = last row(re)/last column (ce) to be used in sheet. re = 0 or ce = 0 results in all rows/columns of sheet to be used
'ri and ci = settings, whether first row/column should be used as an index in table object
Dim VBA_Table As New Table
Dim s As Sheet
s = Parameters.Sheets(XLS_Sheet)
Dim ro As Integer, co As Integer 'Offset für Zeilen-/Spaltenindex
s.BufferEnabled = True
Dim r,c As Integer
If re = 0 Then
re = s.UsedRows
End If
If ce = 0 Then
ce = s.UsedColumns
End If
If ri Then
'Switch row index on and set offset for first column = 0
VBA_Table.RowIndex = True
co = 0
Else
'Set offset for first column = 0
co = 1
End If
If ci Then
'Switch column index on and set offset for first row = 0
VBA_Table.ColumnIndex = True
ro = 0
Else
'Set offset for first row = 0
ro = 1
End If
'pre dimension the table-object to reduce memory usage for large tables
VBA_Table.ColumnCount = ce-cs
VBA_Table.RowCount = re-rs
'write data from sheet into Table
For r = 0 To re-rs
For c = 0 To ce-cs
If r + ro = 0 Or c + co = 0 Then
If CStr(s.CellYX(r+rs,c+cs)) <> "" Then
VBA_Table(r+ro,c+co) = CStr(s.CellYX(r+rs,c+cs))
End If
Else
If IsDate(s.CellYX(r+rs,c+cs)) Then
VBA_Table(r+ro,c+co) = CStr(s.CellYX(r+rs,c+cs))
Else
VBA_Table(r+ro,c+co) = s.CellYX(r+rs,c+cs)
End If
End If
Next
Next
Read_Table = VBA_Table
End Function
Write_Table Funktion
Table -Objekte sind auch sehr nützlich, um benutzerdefinierte Ergebnisse während der Simulation zu speichern und zu verwalten. Im folgenden Beispiel wird der Wert des benutzerdefinierten Attributs CIP Delay pro Einheit in einem Table-Objekt aggregiert.
t_results(cop.Unit.Name,1) += cop.OrderProcedure.CustomAttribute("CIP Delay")
Um die im Table-Objekt gespeicherten Ergebnisse anzuzeigen, können sie am Ende des Simulationslaufs in Excel geschrieben werden, üblicherweise innerhalb einer End_Sim -Prozedur. Dies könnte zellenweise geschehen, indem man die CellYX -Eigenschaft verwendet. Ein derzeitiger Computer würde jedoch ca. 1 s benötigen, um 1000 Zellen zu schreiben. Bei großen Datenmengen kann es zu langen Wartezeiten kommen. Daher wird im zweiten Teil dieses Tipps die Funktion Write eingeführt, mit der das Schreiben etwa hundertmal schneller ausgeführt wird als das Schreiben einzelner Zellen.
Diese Funktion erwartet als Eingabeparameter
- VBA_Table (ein Table-Objekt mit Ergebnissen),
- t_rs und t_cs (erste Zeile und erste Spalte im Table-Objekt),
- t_re and t_ce (letzte Zeile und letzte Spalte im Table-Objekt, 0 for all),
- XLS_Sheet (der Stringname des Excel-Arbeitsblatts),
- s_rs and s_cs (erste Zeile und erste Spalte des zu schreibenden Arbeitsblatts).
Nutzen Sie beispielsweise in der End_Sim Prozedur diesen Code:
Write_Table(t_results,0,0,0,0,"Results",1,1)
Mit diesem Code wird das komplette Table-Objekt in das Blatt t_results geschrieben. Bitte beachten Sie, dass die Indexzeile bzw. die Indexspalte die Nummer 0 hat. Zum Auslesen des Zeilenindex ist 0 die erste Zeile. Mit t_re = 0 werden alle verfügbaren Zeilen selektiert (analog für ce). Sie können natürlich auch das Tabellenobjekt ohne Indizes nach Excel schreiben und nur die Spalten 3-8 ohne die Spalten 1-3 der Blätter überschreiben mit:
Write_Table(t_results,1,3,0,8,"Results",1,4)
Um die Funktion Write_Table verwenden zu können, muss der folgende Code in Ihr Makro kopiert werden:
Sub Write_Table(VBA_Table As Table, t_rs As Long, t_cs As Long, t_re As Long, t_ce As Long, XLS_Sheet As String, s_rs As Long, s_cs As Long) ', ri As Boolean, ci As Boolean)
'Support function for writing VBA table objects into an Excel Sheet using RangeYX method
'VBA_Table = VBA table object
't_rs and t_cs = first row(rs)/first column (cs) of table object. Use t_rs = 0 and t_cs = 0 to include the index
't_re and t_ce = last row(re)/last column (ce) of table object. t_re = 0 or t_ce = 0 results in all rows/columns of sheet to be used
'XLS_Sheet = sheet name of excel sheet as string
's_rs and t_cs = first row/first column of the excel sheet to be used
'set re, ce
Dim r As Long, c As Long
If t_re = 0 Then
t_re = VBA_Table.RowCount
End If
If t_ce = 0 Then
t_ce = VBA_Table.ColumnCount
End If
'set array dimensions
Dim a(,) As Object
ReDim a(t_re-t_rs,t_ce-t_cs)
'writing into array
For r = t_rs To t_re
For c = t_cs To t_ce
If Not IsDBNull(VBA_Table(r,c)) Then
a(r-t_rs,c-t_cs) = VBA_Table(r,c)
End If
Next
Next
'writing array to sheet
Dim s As Sheet
s = Parameters.Sheets(XLS_Sheet)
'(first row, first column, first row + number of rows, first column + number of columns)
s.RangeYX(s_rs, s_cs, s_rs+t_re-t_rs, s_cs+t_ce-t_cs) = a()
End SubWrite_Table(t_results,1,3,0,8,"Results",1,4)
Demo-Projekt
Im Bereich Downloads finden Sie ein Demo-Projekt mit zwei Experimenten: General Understanding und Process Example.
Experiment General Understanding
In diesem Experiment wird in der Simulation_Init -Prozedur eine Excel-Tabelle mit 10000 Werten durch die Read_Table -Funktion in das Tabellenobjekt t_input übertragen. Während der Simulation wird das Tabellenobjekt t_results erzeugt und in der End_Sim-Prozedur mit Hilfe der Write_Table-Funktion in die Excel-Tabelle Results geschrieben. Zum Vergleich wird t_results auch zellenweise in die Excel-Tabelle Results geschrieben, und die besonders benötigte Rechenzeit wird in die Konsole geschrieben.
Experiment Process Example
In diesem Experiment finden Sie die drei Trockner aus unserem ersten Beispiel in diesem Tipp & Trick. Die drei Trockner führen ein einfaches Rezept aus, das nur aus einem Trocknungs- und einem Reinigungsvorgang besteht. Es gibt 3 Trockner mit unterschiedlicher Trocknungsdauer und unterschiedlichem Reinigungsbedarf (nach 2-5 Chargen).
Die Trocknungsdauer in der Parametersteuerung Drying_Duration wird aus dem Tabellenobjekt t_process ausgelesen und der Operation zugeordnet (siehe Beispiel oben).
In der Verknüpfungsbedingung Dryer_Clean wird der benutzerdefinierte BatchCounter mit dem Wert CleanAfterXBatches aus t_process verglichen, um entscheiden zu können, ob der Trockner gereinigt werden muss. Bei der Reinigung wird der Wert in Zelle t_process([dryer name], CleanedXTimes mit 1 addiert.
Sub Dryer_Clean(cond As OrderLinkCondition)
cond.OrderOperationFrom.Unit.CustomAttributes("BatchCounter") = cond.OrderOperationFrom.Unit.CustomAttributes("BatchCounter") + 1
If cond.OrderOperationFrom.Unit.CustomAttributes("BatchCounter") mod t_process(cond.OrderOperationFrom.Unit.Name, "CleanAfterXBatches") = 0 Then
cond.Value = True
t_process(cond.OrderOperationFrom.Unit.Name, "CleanedXTimes") = t_process(cond.OrderOperationFrom.Unit.Name, "CleanedXTimes") + 1
End If
End Sub
In der End_Sim-Prozedur wird bei der Write_Table-Funktion die Spalte 3 (CleanedXTimes) zurück in das Excel-Arbeitsblatt geschrieben.
Write_Table(t_process,1,3,0,3,"Example Process Parameters",2,4)
Das resultierende Gantt-Diagramm zeigt unterschiedliche Trocknungszeiten für die verschiedenen Trockner. Man erkennt auch die unterschiedliche Reinigungsfrequenz (grüne Balken) für die drei Trockner.
Im Bereich Downloads finden Sie das Demo-Projekt und die Read_Table– und Write_Table-Funktionen als Textdokumente.
(Nur für angemeldete INOSIM Nutzer)
- Beispiel-Projekt
- VBA Funktion Read_Table
- VBA Funktion Write_Table
Fragen?
Möchten Sie mehr über dieses Thema erfahren oder haben weitere Fragen? Bitte kontaktieren Sie uns.
Mehr Tipps & Tricks
Die Abfolge von INOSIM Ereignisaufrufen
Erfahrenen Anwendenden von INOSIM ist bewusst, dass sie mit einer ereignisdiskreten Simulationssoftware arbeiten. Für die meisten dieser Ereignisse können VBA-Steuerungen aufgerufen werden, um das Simulationsverhalten…
Nutzen Sie Ihr Excel-VBA-Wissen bei der Arbeit mit INOSIM
Nutzen Sie Ihr Excel-Wissen bei der Arbeit mit INOSIM In diesem Tipp und Trick möchten wir Ihnen zeigen, wie Sie die Standard-Visual Basic Befehle von…
Benutzerdefiniertes Verhalten im Störungsfall
In INOSIM Simulationen können benutzerdefinierte, stochastische Teilanlagen-Störungen genutzt werden, um die Realität in einer Anlage möglichst präzise abzubilden. Mit dem Add-On Statistische Analyse kann dann…