NAV
lua

Introduction

Willkommen zur Holzvogel Lua-Script Dokumentation.

Definitionen

Die nachfolgenden Funktionen stehen in den Definitionen zur Verfügung.

Parameter

Beispiel 1: Abfrage der ID der aktuellen Position


--- Beispiel für Lua-Script des Super-Sets
--- ID "55a20f7e-9bf4-4c20-af2f-2e97ee2e4696"

local MeineAktuelleId = arguments.id

hvm.scope.set('SuperSetId', MeineAktuelleId)

Beispiel 1: Ergebnis

{
    "scope": {
        "SuperSetId": "55a20f7e-9bf4-4c20-af2f-2e97ee2e4696"
    }
}

Beispiel 2: Abfrage des summierten Wertes

--[[
Beispiel für ein Lua-Script einer Leistung mit 3 Definitionen.

Die angelegten Definitionen geben folgende Werte zurück:

Definition 1 = 4.5
Definition 2 = -0.35
Definition 3 = 7.5
Summe = 11,65
]]--

local LeistungSumme = arguments.amount

hvm.scope.set('SummeDerLeistung', LeistungSumme)

Beispiel 2: Ergebnis

{
    "scope": {
        "SummeDerLeistung": 11.65
    }
}

Das System übergibt jedem Lua-Script wichtige Parameter, die von einigen Funktionen innerhalb des Lua-Scripts benötigt werden. Die Parameter können innerhalb des Lua-Scripts jederzeit ausgelesen werden. Die folgenden Parameter stehen in der globalen Variable arguments zur Verfügung:

Variable Positionstypen Datentyp Beschreibung
id alle string Die ID der aktuellen Position, dessen Lua-Script gerade ausgeführt wird
amount Material, Leistung float Summe aus allen Massenwerten der Definitionen unter der Position

hvm.definition

getPositionValue()

local MasseVonPosition = hvm.definition.getPositionValue("55a20f7e-9bf4-4c20-af2f-2e97ee2e4696")

Gibt den berechneten Wert einer anderen Position im Definitionsbaum zurück.

Parameter Datentyp Beschreibung
id string ID der Position (z.B. 55a20f7e-9bf4-4c20-af2f-2e97ee2e4696)

Rückgabe

Datentyp Beschreibung
float | nil Der berechnete Massenwert der Position oder nil, wenn kein Wert ermittelt werden konnte

getWorkTime()

Beispiel 1: Abfrage der Zeiten von allen Arbeitspaketen für aktuelle Position

local Zeiten = hvm.definition.getWorkTime(arguments.id)

Beispiel 2: Abfrage der Zeiten nur für die angegebenen Arbeitspakete

-- Zeiten mit Arbeitspakets "MO" abfragen
local ZeitAPs = hvm.definition.getWorkTime(arguments.id, { "MO" })

-- Zeiten mit Arbeitspakete "PR" und "MO" abfragen
local ZeitAPs = hvm.definition.getWorkTime(arguments.id, { "PR", "MO" })

--[[
// Ausgabe von ZeitAPs

{
    "total": 40.5,
    "packages": {
        "PR": 30.5,
        "MO": 10
    }
}
--]]

-- Zugriff auf Summe der Zeiten mit Fallback 0 wenn Wert nicht vorhanden
local GesamtZeit = ZeitAPs["total"] or 0 

-- Zugriff auf eine bestimmte Zeit eines Arbeitspakets
-- mit Fallback auf 0, wenn keine Zeit zu AP gefunden wurde
local AP_PR_Zeit = ZeitAPs["packages"]["PR"] or 0  -- Ergebnis: 30.5
local AP_MO_Zeit = ZeitAPs["packages"]["MO"] or 0  -- Ergebnis: 10

local AP_Zeit_Fehlt = ZeitAPs["packages"]["FF"] or 0   -- Ergebnis: 0

Gibt die Zeit für Eigenleistungen als Summe und gruppiert nach Arbeitspaketen zurück. Über den zweiten Parameter kann mit einer Tabelle angegeben werden, ob die Arbeitszeiten auf eine oder mehrere Arbeitspakete beschränkt werden soll.

Parameter Datentyp Benötigt? Beschreibung
id string ja Die ID der Position, dessen Zeiten abgefragt werden sollen
workPackageNames table nein Arbeitspakete als maschinenlesbare Namen auf welches das Ergebnis eingeschränkt werden soll

Ergebnis:

Datentyp Beschreibung
table Gesamtzeit und Zeit nach Arbeitspaketen in einer Lua-Tabelle
Name Datentyp Beschreibung
total float Gesamtzeit in Minuten
packages table Zeiten nach Arbeitspaketen mit maschinenlesbarer Name als Schlüssel und Zeit in Minuten als Wert

getProjectSupplierDistances()

local LieferantenEntfernung = hvm.definition.getProjectSupplierDistances();

Beispielausgabe für ein Projekt

{
    "abbund": 36,
    "architekt": 49,
    "bodenleger_parket": 33,
    "bodenleger_sonstige": 33,
    "dach_deckenelemente": 17,
    "dachabdichtung": 17,
    "dacheindeckung": 17,
    "daemmarbeiten": 17,
    "enev": 17,
    "estrich": 5,
    "fassadenbau": 17,
    "fenster": 13,
    "fliesenleger": 72,
    "garagentor": 0,
    "gartenplanung": 43,
    "geruest": 229,
    "heizung": 68,
    "holzbau_montage": 17,
    "holzbau_produktion": 17,
    "kamin": 17,
    "kran": 41,
    "lueftung": 68,
    "malerarbeiten": 156,
    "massivholzwaende": 188,
    "pv_anlage": 68,
    "rohbau": 17,
    "rohbau_aussenanlagen": 17,
    "rohbau_keller": 17,
    "sanitaer": 68,
    "sanitaer_dusche": 68,
    "schlosser": 20,
    "schreiner": 17,
    "spengler": 17,
    "statik": 10,
    "terrassen": 17,
    "transport_holzbau": 17,
    "treppenbau": 17,
    "trockenbau": 156,
    "verputzer_aussen": 17,
    "verputzer_innen": 17,
    "verschattung": 23,
    "werkplanung": 17
}

Abfrage aller Entfernungen von den ausgewählten Lieferanten des Projekts zur Baustellenadresse des aktuellen Projekts nach Gewerke.

Ergebnis:

Datentyp Beschreibung
table Lua-Tabelle mit Gewerke als Schlüssel und Entfernung in Kilometer als zugehöriger Wert

getProjectSupplierDistanceFor()

Beispiel: Abfrage des Lieferanten für das Gewerke "Schlosser" zur Baustellenadresse.

local LieferantEntfernung = hvm.definition.getProjectSupplierDistanceFor("schlosser")

Gibt die Entfernung des hinterlegten Lieferanten zu einem Gewerke zur Baustellenadresse des aktuellen Projekts zurück.

Parameter Datentyp Benötigt? Beschreibung
machineName string ja Der maschinenlesbare Name des Gewerkes

Ergebnis:

Datentyp Beschreibung
float Entfernung in Kilometer

outputExcelFile()

local ExcelDateiPfad = "data/storage/content/beispiel.xlsx"

-- Erstellung der Excel-Datei
local Workbook = require "xlsxwriter.workbook"

local workbook  = Workbook:new(ExcelDateiPfad)  -- Hier den Pfad zur Excel-Datei angeben
local worksheet = workbook:add_worksheet()

worksheet:write("A1", "Hello world")
workbook:close()

-- Ausgabe an das Multitool zur Anzeige
hvm.definition.outputExcelFile(ExcelDateiPfad)

Die Funktion weist das Multitool an, die Excel-Datei zum angegebenen Pfad an das Frontend weiterzuleiten, sodass die Excel-Datei in der Ansicht angezeigt werden kann.

Parameter Datentyp Benötigt? Beschreibung
filePath string ja Vollständiger Pfad zur Excel-Datei

selectPositionsBySize()

Beispiel 1

local SuperSetId = "96af3b7f-2616-403b-8ee8-f67c8252587f"
local Beispiel1  = { 
                       { "Maß1"=1.01, "Maß2"=2.135 },
                       { "Maß1"=0.885, "Maß2"=2.135 }
                   }
local Ergebnis1  = hvm.definition.selectPositionsBySize(SuperSetId, Beispiel1)

Beispiel 2 (mit Optionen)

local SuperSetId = "96af3b7f-2616-403b-8ee8-f67c8252587f"
local Beispiel2  = { 
                       { "Breite"=1.01, "Höhe"=2.135 },
                       { "Breite"=0.885, "Höhe"=2.135 },
                   }
local Optionen   = { "width": "Breite", "height": "Höhe" }

local Ergebnis2  = hvm.definition.selectPositionsBySize(SuperSetId, Beispiel2, Optionen)

Beispiel 3 - Einsatz mit getImportValueByRules() im Super-Set

local SuperSetId = "96af3b7f-2616-403b-8ee8-f67c8252587f"
local Regeln = {
    {
        type="Search",
        selector="TT_1_1",
        columns={"Maß1", "Maß2", "GG", "Ident_Text", "E2", "E12"},
        criteria={
           GG="1",
           E2={"1", "2"},
           E12={"11", "12"},
           E6={"0","1"}
        }
    }
}

local Elemente = hvm.quantity.getValueByRules(Regeln)

-- Selektiere alle Positionen mit der Größe aus Elemente 
local Ergebnis3 = hvm.definition.selectPositionsBySize(SuperSetId, Elemente)

Ergebnis bei exakten Größen

{
    "1010:2135": 1,
    "885:2135": 2
}

Ergebnis bei nicht exakten Ergebnissen

{
    "1010:2235": 1,
    "1010:2260": 2
}

Gibt eine Liste an Positionen mit der Menge aus einem Super-Set anhand der angegebenen Größen zurück. Falls die exakte Größe im Super-Set nicht gefunden wurde, dann wird die nächstgrößere Position aus der Breite und Höhe ermittelt.

Parameter Datentyp Benötigt? Beschreibung
super_set_id string ja Die ID des Super-Sets
positions object[] ja Eine Liste mit Objekten, die Werte für die Breite und Höhe als Eigenschaften enthalten
options object nein Optionen zur Anpassung des Funktionsverhaltens - siehe unten

Rückgabe

Datentyp Beschreibung
table Liste der gefundenen Positionen mit Größe und Menge

Optionen

Als dritter Parameter kann ein Objekt mit Optionen übergeben werden. Die folgenden Optionen können gesetzt werden.

Name Datentyp Beschreibung
width string Feldname für die Breite
height string Feldname für die Höhe

setItemOptions()

Beispiel 1: Nur den Titel setzen

local Optionen = {
    title="Mein neuer Titel"
}

hvm.definition.setItemOptions(Optionen)

Beispiel 2: Nur Anzeigeoptionen anpassen

local Optionen = {
    viewOptions={
        asShortText=true,
        alternative=false,
        circa=true
    }
}

hvm.definition.setItemOptions(Optionen)

Beispiel 3: Titel und andere Anzeigeoptionen setzen


local Optionen = {
    title="Titel mit veränderten Anzeigeoptionen",
    onlyPositive=true,
    viewOptions={
        asShortText=true,
        circa=true
    }
}

hvm.definition.setItemOptions(Optionen)

Besipiel 4: Alle Optionen mit eigenen Werten setzen und überschrieben Tipp: Versuchen sie, wenn möglich nur Optionen zu setzen, die sich auch wirklich ändern. Dies spart Speicherplatz ein und erhöht die Performance.


--- Änderung aller möglichen Optionen

local Optionen = {
    title="Neuer Titel für Position",
    printTitle="Mein spezieller Drucktitel",
    extraText="Mein Zusatztext für die Anzeige im Druck",
    priceModifier=20,
    onlyPositive=true,
    forceNegative=false,
    enabled=false,
    viewOptions={
        asNeeded=true,
        alternative=true,
        circa=true,
        withoutPrice=true,
        blanket=false,
        withoutCalc=false,
        asShortText=true,
        asLongText=false,
        hide=false
    }
}

hvm.definition.setItemOptions(Optionen)

Setzt und überschreibt die statischen Optionen der aktuellen Position im Lua-Script.

Bei der Übergabe erwartet die Funktion mindestens eine Option in der Lua-Tabelle im ersten Parameter. Dabei werden nur die Optionen überschrieben, die an die Funktion übergeben werden. Es können alle Optionen oder nur ein Teil der Optionen überschrieben werden.

Parameter Datentyp Benötigt? Beschreibung
options table ja Lua-Tabelle mit Namen und Werte der Optionen

Liste der verfügbaren Optionen

Name Datentyp Beschreibung
title string Titel der Position
printTitle string Titel für den Druck
extraText string Zusatztext für den Druck
priceModifier float Abschlag oder Zuschlag in % (als positiver oder negativer Wert)
onlyPositive boolean Nur positive Werte erlauben
forceNegative boolean Erzwinge negativen Wert
enabled boolean Position wird aktiviert (true) und deaktiviert (false)
ignoreSystemQuantity boolean Setzt die Option "Mengen von System nicht aktualisieren" in Positionen von Dokumenten
viewOptions table Optionen zur Anzeige der Position (siehe Anzeigeoptionen)

Liste der Anzeigeoptionen

Name Datentyp Beschreibung
asNeeded boolean Bei Bedarf
alternative boolean Alternativ
circa boolean ca.
withoutPrice boolean Ohne Preis
blanket boolean Pauschal
withoutCalc boolean Ohne Berechnung
asShortText boolean Als Kurztext
asLongText boolean Als Langtext
hide boolean Ausblenden

hvm.quantity

getValueByRules()

Beispiel: Einzelne Abfrage mit dem summierten Massenwert

local Regeln = {
    {
        type="Search",
        selector="AW_3_1",
        columns={"Wert1"},
        criteria={
            ["Maß1"]= GlobalHolzbauWand280,
            ["E8"]= "0"
        }
    },
    {
        -- Summiere alle Werte in Spalte "Wert1" aus den übergebenen Daten der letzten Regel
        type="Summary",
        column="Wert1"
    }
}

local Ergebnis = hvm.quantity.getValueByRules(ruleset)

Beispiel: Abfrage von einzelnen Massenwerten und der summierten Masse in getrennten Ergebnissen

local Wandlaengen_Holzbau_EG = {
    {
        type="Search",
        selector="AW_3_1",
        columns={"Wert1"},
        criteria={
            ["Maß1"]= GlobalHolzbauWand280,
            ["E8"]= "0"
        }
    }
}

local Wandlaengen_Holzbau_EG_Summe = {
    {
        -- Summiere alle Werte in Spalte "Wert1" aus den übergebenen Daten der letzten Regel
        type="Summary",
        column="Wert1"
    }
}

-- Abfrage der einzelnen Wandlängen und in Variable speichern
local Wandlaengen = hvm.quantity.getValueByRules(Wandlaengen_Holzbau_EG)

-- Abfrage der Summe der Wandlängen, wobei die einzelnen Wandlängen (Basis der zweiten Abfrage) über die Variable
-- Wandlaengen an die Funktion übergeben werden
local Wandlaengen_Summe = hvm.quantity.getValueByRules(Wandlaengen_Holzbau_EG_Summe, Wandlaengen)

hvm.scope.set('Wandlaengen', Wandlaengen)
hvm.scope.set('Wandlaengen_Summe', Wandlaengen_Summe)

return Wandlaengen_Summe

Rückgabe von Werten aus dem Massenimport anhand der Angabe von Regeln.

Über den optionalen zweiten Parameter payload können weitere Regeln auf ein bereits bestehendes Ergebnis aus einer anderen Abfrage angewendet werden. Dies minimiert die Abfragen und Duplizierung von Regeln, wenn Zwischenergebnisse aus einzelnen Regeln weiter bearbeitet werden sollen.

Parameter Datentyp Benötigt? Beschreibung
ruleset array ja Ein Set an Regeln zur Abfrage der Massen
payload mixed nein Angabe eines Ergebnisses aus einer vorherigen Abfrage

Rückgabe

Datentyp Beschreibung
any Je nach Angabe der Regeln ein einzeolner Wert oder mehrere Werte in einer Liste

Veraltete Funktionen

Die nachfolgenden Funktionen sind nur noch aus Kompatibiliätsgründen zu alten Lua-Scripts vorhanden. Bitte verwenden Sie immer die neuen Funktionen und versuchen sie veraltete Funktionen in bestehenden Scripten zu entfernen.

getImportValueByRules()

Alias für hvm.quantity.getValueByRules()

getPositionValue()

Alias für hvm.definition.getPositionValue()

selectPositionsBySize()

Alias für hvm.definition.selectPositionsBySize()

Debugging

hvm.debug

Die nachfolgenden Funktionen werden nur zur Anzeige von Debug-Informationen verwendet und werden nur verarbeitet, wenn Lua-Scripte einzeln ausgeführt werden, z.B. bei der Bearbeitung der Definitionen.

set()

local WertFuerDebug = 150

hvm.debug.set("MeinName", WertFuerDebug)

--- in einem anderen Lua-Script auf höhere Ebene
local WertVonDebug = hvm.scope.get("MeinName")

--- WertvonDebug = 150

Setzen eines Wertes im Debugging

Parameter Datentyp Beschreibung
name string Der Name unter dem der Wert gespeichert werden soll
value any Der zu speicherende Wert

get()

hvm.scope.set("NameImDebug", 295)

local WertImDebug = hvm.debug.get("NameImDebug")   --- Ausgabe: 295

local WertImDebug = hvm.debug.get("nameimdebug")   --- Ausgabe: nil
local WertImDebug = hvm.debug.get("NAMEimDEBUG")   --- Ausgabe: nil

Gibt den Wert unter dem angegebenen Namen zurück.

Parameter Datentyp Beschreibung
name string Der Name dessen Wert gelesen werden soll
Datentyp Beschreibung
any Der gespeicherte Wert unter dem Namen im Debug, andernfalls nil wenn nicht vorhanden

remove()

hvm.debug.set("NameImDebug", 500)

local WertImDebug = hvm.scope.get("NameImDebug")   --- Augabe: 500

hvm.debug.remove("NameImDebug")

local WertImDebug = hvm.debug.get("NameImDebug")   --- Ausgabe: nil

Löscht den Schlüssel inklusive dem Wert aus dem Debug

Parameter Datentyp Beschreibung
name string Der Name dessen Wert aus dem Debug gelöscht wird

has()

local NameImDebug = "foobar"

hvm.scope.set("NameImDebug", "foobar")

local WertVorhanden = hvm.debug.get("NameImDebug")  --- Ausgabe: true

hvm.scope.remove("NameImScope")

local WertVorhanden = hvm.debug.has("NameImDebug")  --- Ausgabe: false

Prüft ob ein Wert unter dem Namen im Debug vorhanden ist

Parameter Datentyp Beschreibung
name string Der Name dessen Wert aus dem Debug gelöscht wird
Datentyp Beschreibung
boolean TRUE = vorhanden - FALSE = nicht vorhandnen

clear()


hvm.debug.set("NameImScope", "foo")
hvm.debug.set("NameImScope2", "bar")

hvm.debug.clear()

hvm.debug.get("NameImScope")    --- Ausgabe: nil
hvm.debug.get("NameImScope2")   --- Ausgabe: nil

Löscht alle vorhandenen Werte innerhalb des Debug-Bereichs.

Scope

Der Scope ist ein Speicherbereich für Werte, die zwischen dem Multitool und den Lua-Scripts verwendet werden kann. Innerhalb von Lua-Scripte können beliebige Werte unter einem Namen im Scope gespeichert, verändert oder gelöscht werden. Das Multitool kann diese Werte aus reservierten Namen auslesen und für die weitere Bearbeitung im System verwenden (z.B. das Auslösen weiterer Aktionen im System). Zusätzlich können Lua-Scripte untereinander Daten über den Scope austauschen, solange der Datenfluss von tieferen Positionen zu höheren Positionen im Definitionsbaums erfolgt.

hvm.scope

Die nachfolgenden Funktionen werden für das Verwalten verwendet.

set()

Beispiel 1: Eine Variable im globalen Bereich schreiben

local WertFuerScope = 150

hvm.scope.set("NameImScope", WertFuerScope)

--- in einem anderen Lua-Script auf höhere Ebene
local WertVomScope = hvm.scope.get("NameImScope")  -- Ausgabe: 150

Beispiel 2: Eine Variable in einem speziellen Namensraum speichern


local WertFuerScope = 100

hvm.scope.set("NameImScope", WertFuerScope, "foo")

local WertVomScope1 = hvm.scope.get("NameImScope", "foo") -- Ergebnis: 100

local WertVomScope2 = hvm.scope.get("NameImScope")  -- Ergebnis: nil (keine Variable vorhanden), da globaler Bereich

Setzen eines Wertes im Scope unter dem angegebenen Namen.

Mit dem dritten Parameter kann optional ein Namensraum angegeben werden, in dem die Variable gespeichert werden soll.

Parameter Datentyp Beschreibung
name string Der Name unter dem der Wert gespeichert werden soll
value any Der zu speicherende Wert
namespace string Namensraum für Variable

get()

Beispiel: Variablen im globalen Bereich abfragen

hvm.scope.set("NameImScope", 295)

local WertVomScope1 = hvm.scope.get("NameImScope")   --- Ausgabe: 295

local WertVomScope2 = hvm.scope.get("nameimscope")   --- Ausgabe: nil

local WertVomScope3 = hvm.scope.get("NAMEimSCOPE")   --- Ausgabe: nil

Beispiel 2: Variablen in einem speziellen Namespace abfragen

hvm.scope.set("NameImScope", 200, "foo")

local WertVomScope1 = hvm.scope.get("NameImScope", "foo")  -- Ausgabe: 200

local WertVomScope2 = hvm.scope.get("NameImScope")  -- Ausgabe: nil (keine Variable vorhanden)

Gibt den Wert unter dem angegebenen Namen zurück.

Wenn der zweite Parameter angegeben wird, dann wird die Variable aus dem angegebenen Namensraum gelesen.

Parameter Datentyp Beschreibung
name string Der Name dessen Wert gelesen werden soll
namespace string (optional) Namensraum der Variable
Datentyp Beschreibung
any Der gespeicherte Wert unter dem Namen im Scope, andernfalls nil wenn nicht vorhanden

remove()

Beispiel 1: Wert im globalen Bereich löschen

hvm.scope.set("NameImScope", 500)

local WertImScope1 = hvm.scope.get("NameImScope")   --- Augabe: 500

hvm.scope.remove("NameImScope")

local WertImScope2 = hvm.scope.get("NameImScope")   --- Ausgabe: nil

Beispiel 2: Wert in einem speziellen Namensraum löschen

hvm.scope.set("NameImScope", 500, "foo")

local WertImScope1 = hvm.scope.get("NameImScope", "foo")   -- Ausgabe: 500

hvm.scope.remove("NameImScope", "foo")

local WertImScope3 = hvm.scope.get("NameImScope")  -- Ausgabe: nil (Variable nicht in globalen Bereich vorhanden)

local WertImScope2 = hvm.scope.get("NameImScope", "foo")  -- Ausgabe: nil (wurde gelöscht)

Löscht den Schlüssel inklusive dem Wert aus dem Scope

Wenn der zweite Parameter für den Namensraum angegeben wird, dann wird die Variable aus dem angegebenen Namensraum gelöscht.

Parameter Datentyp Beschreibung
name string Der Name dessen Wert aus dem Scope gelöscht wird
namespace string (optional) Namensraum der Variable

has()

Beispiel 1: Prüfen auf Variable im globalen Bereich

local NameImScope = "foobar"

hvm.scope.set("NameImScope", "foobar")

local WertVorhanden = hvm.scope.has("NameImScope")  --- Ausgabe: true

hvm.scope.remove("NameImScope")

local WertVorhanden = hvm.scope.has("NameImScope")  --- Ausgabe: false

Beispiel 2: Prüfen auf eine Variable in einem speziellen Namensraum

local NameImScope = "bar"

hvm.scope.set("NameImScope", "bar", "foo")

local WertVorhanden1 = hvm.scope.has("NameImScope", "foo")  -- Ausgabe: true

local WertVorhanden2 = hvm.scope.has("NameImScope")  -- Ausgabe: false

Prüft ob ein Wert unter dem Namen im Scope vorhanden ist.

Wenn der zweite Parameter angegeben wird, dann wir im angegebenen Namensraum geprüft, ob die Variable vorhanden ist.

Parameter Datentyp Beschreibung
name string Der Name dessen Wert aus dem Scope gelöscht wird
namespace string (optional) Namensraum der Variable
Datentyp Beschreibung
boolean TRUE = vorhanden - FALSE = nicht vorhandnen

clear()

Beispiel 1: Alle Variablen im globalen Bereich und in allen Namespaces löschen


hvm.scope.set("NameImScope", "foo")
hvm.scope.set("NameImScope2", "foo")

hvm.scope.clear()

hvm.scope.get("NameImScope")    --- Ausgabe: nil
hvm.scope.get("NameImScope2")   --- Ausgabe: nil

Beispiel 2: Alle Variablen in einem speziellen Namensraum löschen

hvm.scope.set("NameImScope1", "foobar1", "foo")
hvm.scope.set("NameImScope2", "foobar2", "foo")

hvm.scope.clear("foo")

hvm.scope.get("NameImScope1", "foo")  -- Ausgabe: nil
hvm.scope.get("NameImScope2", "foo")  -- Ausgabe: nil

Löscht alle vorhandenen Werte innerhalb des Scopes

Wenn der Namensraum als Parameter angegeben, dann werden alle Variablen im angegebenen Namensraum gelöscht.

Parameter Datentyp Beschreibung
namespace string (optional) Namensraum der Variable

Globale Funktionen

hvmGetTableValue()

local Kunde = {
    vorname="Max",
    nachname="Mustermann",
    stadt="Musterstadt",
    telefon=nil,
    alter=40
}

local Vorname = hvmGetTableValue(Kunde, "vorname")
-- Ausgabe: Max (string)

local NichtVorhanden = hvmGetTableValue(Kunde, "geburtstag")
-- Ausgabe: 0

local VorhandenMitNil = hvmGetTableValue(Kunde, "telefon")
-- Ausgabe: 0

local Alter = hvmGetTableValue(Kunde, "alter")
-- Ausgabe: 40

Gibt einen Wert aus einer Lua-Tabelle mit dem angegebenen Feldnamen zurück.

Die Funktion prüft auf das Vorhandensein des Feldnamen und gibt den Wert 0 als Ganzzahl zurück, wenn das Feld mit dem Namen nicht exisitiert oder der Wert nil enthalten ist.

function hvmGetTableValue(source, key): number

Parameter Datentyp Beschreibung
source table Die Lua-Tabelle mit Daten
key string Name des Feldes

hvmScopesToString(query)


local query = {
    scopes={
        "Name_1",
        "Name_2",
        "Name_3",
        "Name_4",
        "Name_5",
        "Name_6",
        "Name_7",
        "Name_8"
    },
    separator=", ",
    fields={
        "Wert2",
        "Ident_Text",
        "Bezeichnung",
        "BezID1",
        "GG",
        "BTNr",
        "EleID",
        { name="MeinFeld", suffix=" Stück" }    -- Angabe einer Zeichenkette suffix an den Wert des Feldes "MeinFeld"
    },
    groupBy="GG",
    groupNewLine=true,
    floors={
        ["0"]="KELLERGESCHOSS",
        ["1"]="ERDGESCHOSS",
        ["2"]="1OG",
        ["3"]="2OG",
        ["4"]="3OG",
        ["98"]="DACHGESCHOSS"
    }
}

local Ergebnis = hvmScopesToString(query)

-- Das Ergebnis enthält einen String, der beispielsweise in den Zusatztext einer Position
-- geschrieben werden kann. 

Wandelt Listen in angegebenen Scope-Bereichen in einen Plain-Text als Auflistung um und gibt einen String zurück

Parameter Datentyp Beschreibung
query table Tabelle mit Informationen zur Ausgabe der Liste (siehe unten)

Optionen der Query

Parameter Datentyp Beschreibung
scopes table Liste von Variablennamen zur Abfrage der Daten aus dem Scope
separator string Eine oder mehrere Zeichen zum Trennen der einzelnen Spaltenwerte in einer Datenzeile
fields table Liste der Spalten- bzw. Feldnamen in den Datenzeilen, die ausgegeben werden
groupBy string Name der Spalte oder des Feldes nach der die Datenzeilen gruppiert werden
groupNewLine boolean Neue Zeile vor Beginn einer neuen Gruppe einfügen. Ja = true, Nein = false
floors table Tabellen mit Mapping-Informationen zu den Geschossen. Die Tabelle muss einen Schlüssel mit den Bezeichnungen als Wert enthalten

pairsByKeys()

Beispieldaten

local Positionen = {
    {
        Wert1="20.23586",
        Bezeichnung="Außenwandflächen - in der Wandachse",
        EleID="520838188400392",
        BTC="5",
        Ident_Text="AW-11"
    },
    {
        Wert1="10.26453",
        Bezeichnung="Außenwandflächen - in der Wandachse",
        EleID="497475611102084",
        BTC="1",
        Ident_Text="AW-07"
    },
    {
        Wert1="25.82326",
        Bezeichnung="Außenwandflächen - in der Wandachse",
        EleID="344467751086098",
        BTC="2",
        Ident_Text="AW-08"
    }
}

Beispiel 1: Sortierung nach dem Feld "Ident_Text"

local PositionenSortiert = {}
for _, position in pairsByKeys(Positionen, "Ident_Text") do
    table.insert(PositionenSortiert, position)
end

hvm.scope.set('Ergebnis', PositionenSortiert)

Beispiel 1: Ergebnis

{
    "scope": {
        "Ergebnis": {
            "1": {
                "BTC": "1",
                "Ident_Text": "AW-07",
                "Wert1": "10.26453",
                "EleID": "497475611102084",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "2": {
                "BTC": "2",
                "Ident_Text": "AW-08",
                "Wert1": "25.82326",
                "EleID": "344467751086098",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "3": {
                "BTC": "5",
                "Ident_Text": "AW-11",
                "Wert1": "20.23586",
                "EleID": "520838188400392",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            }
        }   
    }
}

Beispiel 2: Sortierung nach dem Feld "BTC" aufsteigend

local PositionenSortiert = {}
for _, position in pairsByKeys(Positionen, "BTC", "desc") do
    table.insert(PositionenSortiert, position)
end

hvm.scope.set('Ergebnis', PositionenSortiert)

Beispiel 2: Ergebnis

{
    "scope": {
        "Ergebnis": {
            "1": {
                "BTC": "5",
                "Wert1": "20.23586",
                "Bezeichnung": "Außenwandflächen - in der Wandachse",
                "EleID": "520838188400392",
                "Ident_Text": "AW-11"
            },
            "2": {
                "BTC": "2",
                "Wert1": "25.82326",
                "Bezeichnung": "Außenwandflächen - in der Wandachse",
                "EleID": "344467751086098",
                "Ident_Text": "AW-08"
            },
            "3": {
                "BTC": "1",
                "Wert1": "10.26453",
                "Bezeichnung": "Außenwandflächen - in der Wandachse",
                "EleID": "497475611102084",
                "Ident_Text": "AW-07"
            }
        }   
    }
}

Sortiert die Elemente in einer Tabelle nach einem Feld und Sortierungsrichtung. Diese Funktion gibt einen Callback für Iteratoren zurück und wird hauptsächlich in einem for in-Block verwendet.

Parameter Datentyp Beschreibung
items table Tabellen, die vereint werden sollen (pro Parameter eine Tabelle)
sortBy string Name des Feldes nach dem sortiert werden soll
order string Aufsteigende oder absteigende Sortierung. "asc" = absteigend (Standard), "desc" aufsteigend

table_merge()

Beispiel 1

local Kunde1 = {
    vorname="Max",
    nachname="Mustermann",
    alter=30
}

local Kunde2 = {
    stadt="Musterstadt",
    alter=40
}

local Kundenliste = table_merge(Kunde1, Kunde2)

Ergebnis

{
    "vorname": "Max",
    "nachname": "Mustermann",
    "stadt": "Musterstadt",
    "alter": 40
}

Vereint mehrere Tabellen zu einer Tabelle, wobei Felder der Tabellen jeweils von den nachfolgenden Tabellen überschrieben werden.

function table_merge(...): table

Parameter Datentyp Beschreibung
... table Tabellen, die vereint werden sollen (pro Parameter eine Tabelle)

Beispiele

In diesem Bereich finden sie einige Bespiele und Erklärungen zu den Lua-Scripten.

LUA-Erläuterung

local Regeln = {

    -- Regel: Suche nach Datensätzen im Import
    {
        -- Parameter: type
        -- Typ der Regel
        -- Mögliche Werte:
        --  "Search"  : Suche nach Datensätzen und gebe Ergebnis an die nächste Regel weiter
        --  "Summary" : Summiert alle Werte mit dem Spaltennamen in der letzten Regel
        type="search",

        -- Parameter: selector
        -- Selektor zur Abfrage von BT, BTNr, BTUNr (jeweils getrennt durch Unterstrich "_")
        -- Gibt alle Werte aus BT=LO, BTNr=1, BTUNr=1 zurück.
        selector="LO_1_1",

        -- Mehreren Selektoren können als Array angegeben werden. Alle Selektoren werden mit einem OR verknüpft.
        selector={"LO_1_1", "WS_1_1"},

        -- Parameter: columns [optional]
        -- Liste der Spaltennamen, dessen Werte im Ergebnis erscheinen sollen
        -- Wenn dieser Parameter nicht vorhanden ist, dann werden die Werte aller Spalten
        -- zurückgegeben (nicht empfohlen - sehr langsame Abfragen)
        columns={"Wert1", "Wert2", "Maß1"},

        -- Parmeter: groupBy [optional]
        -- Gruppierung der Werte nach Spaltenname
        -- (z.B. bei Abfrage von IDs, die im Ergebnis nur einmal vorkommen sollen)
        groupBy={"Wert1"},

        -- Parameter: criteria [optional]
        -- Liste der Bedingungen für die Abfrage von Datensätzen
        --
        -- Die Bedingungen werden mit Spaltenname (links) und dem Wert (rechts) angegeben.
        -- Enthält der Wert einen Spaltennamen in eckigen Klammern, dann interpretiert das System einen Platzhalter.
        -- Platzhalter werden automatisch durch den Wert aus dem Ergebnis der letzten Regel ersetzt
        criteria={
            -- Beispiele für Bedingungen
            EleID="[BezID1]",                   -- EleID mit dem Wert aus der Spalte "BezID1" aus dem Ergebnis der letzten Regel
            E7="1",                             -- Findet alle Datensätze mit dem Wert 1 in Spalte E7
            Wert1={"Kinderzimmer", "Küche"},    -- Findet alle Datensätze mit den Werten "Kinderzimmer" oder "Küche" in Spalte Wert1
            Wert1="Kinderzimmer",               -- Findet alle Datensätze mit dem Wert "Kinderzimmer" in Spalte Wert1

            -- Beispiele für Vergleiche
            { field="Wert1", operator="<", value="0.256"},  -- Schreibweise für Vergleiche mit "<" "<=" "=" "<>" ">=" ">"
            { field="Wert1", operator=">", value="0.5" }
        }
    },

    -- Regel: Berechnung von Werten 
    {
        -- Parameter: type
        -- Typ der Regel (siehe oben)
         type="calculate",

        -- Parameter: formulas [Array]
        -- Formeln für Berechnungen

        -- Aufbau der Formeln
        -- In jeder Formel muss ein Feld (field) und eine Formel (formula) angegeben werden.
        --
        -- Der Feldname kann eine Spalte sein oder ein bestehendes Feld aus einer vorherigen Berechnung. Wenn das Feld noch nicht
        -- existiert, dann wird dieses im Datensatz mit dem Namen hinzugefügt.
        --
        -- Die Formel enthält einen mathematischen Ausdruck.
        -- In der Formel kann durch die Angabe eines Feldnamens eingeschlossen in eckigen Klammern auf den Wert im Datensatz 
        -- auf die Werte der vorherigen Regel oder auf ein Feld der vorherigen Berechnung zugegriffen werden.
        -- Die Formeln werden von oben nach unten abgearbeitet und jeweils auf alle Datensätze der vorherigen Regeln angewendet. 
        --
        -- Operatoren: +, -, *, /, ^ (Exponential)
        -- Funktionen: sqrt, abs, sin, cos, tan, log, exp
        -- Konstanten: pi
        formulas={
            -- Multipliziert den Wert in Spalte "Wert1" mit 200 und schreibt das
            -- Ergebnis in das Feld "meinErgebnis"
            { field="meinErgebnis", formula="[Wert1] * 200" },

            -- Addiert den Wert "meinErgebnis" aus der vorherigen Berechnung mit 25, dividiert durch 100
            -- und schreibt das Ergebnis der Berechnung das Feld "Wert1".
            -- Es können bestehende Spalten überschreiben werden oder neue Felder angegeben werden
            { field="Wert1", formula="([meinErgebnis] + 25) / 100" }
        }
    },
{
        type="calculate",
        formulas={
            -- Multipliziert den Wert in Spalte "Wert1" mit 200 und schreibt das
            -- Ergebnis in das Feld "meinErgebnis"
            { field="meinErgebnis", formula="[Wert1] * [Maß1]" }
        }
    },
    -- Regel: Summierung von Werten
    {
        -- Parameter: type
        -- Typ der Regel (siehe oben)
        type="summary",

        -- Parameter: column
        -- Summierung aller Werte aus der angegebenen Spalte aus dem Ergebnis der vorherigen Regel
        column="Wert1",

        -- Summierung aller Werte aus mehreren Spalten
        -- Alle Spalten müssen in der letzten Regel angegeben sein, andernfalls wird für nicht vorhandene
        -- Spalten der Wert 0 gerechnet. Die Werte werden in der Reihenfolge zusammengerechnet wie diese
        -- angegeben werden.
        column={"Wert1", "Wert2"},

        -- Flag zur Ausgabe der Summierung als separate Spaltensummen oder Summe über alle Spalten
        -- separate=true  : Ausgabe der Summen pro Spalte. Rückgabe ein Array mit den Summen. 
        --                  (z.B. result['Wert1'], result['Wert2'], ...)
        -- separate=false : Ausgabe der Gesamtsumme über alle Spalten. Rückgabe eine Zahl (Float)
        separate=true
    }
}

local Ergebnis = hvm.quantity.getValueByRules(Regeln)

-- Wenn die Summen pro Spalte vorliegen
-- local Wert1Summe = result['Wert1']
-- local Wert2Summe = result['Wert2']
-------------------------------------------------------------------------------

return Ergebnis

Erläuterung der Regeln für die Abfrage der Massen mit hvm.quantity.getValueByRules()

LUA - Problem 1

local Problem1 = {
    {
        -- Regel 1: Suche LO_1_1 BezID5 (Id Wand an OK Loch)
        type="Search",
        selector="LO_1_1",
        columns={"BezID5"}, -- Nur Werte aus diesen Spalten zurückgeben
        groupBy={"BezID5"}
    },
    {
        -- Regel 2: Suche in WS_3_2(z.B.) die ELeID mit dem Wert BezID5 von LO_1_1 und Feld E7 = 1
        type="Search",
        selector="WS_3_2",
        columns={"Wert1"},
        criteria={
            EleID="[BezID5]",
            E7="1"
        }
    },
    {
        -- Regel 3: Summiere alle Werte in Spalte "Wert1" aus den übergebenen Daten der letzten Regel
        type="Summary",
        column="Wert1"
    }
}

return hvm.quantity.getValueByRules(Problem1)

Abfolge der Regeln:

LUA - Problem 2

local Problem2 = {
    {
        -- Regel 1: Suche IS_1_1 BezID1(ID des Raumes in dem sich das Symbol befindet
        type="Search",
        selector="IS_1_1",
        columns={"BezID1"},
        groupBy={"BezID1"}
    },
    {
        -- Regel 2: Suche in RM_10_1(z.B.) die ELeID mit dem Wert BezID1 von IS_1_1
        -- und filtere den Wert2 nach einen oder mehreren Werten
        type="Search",
        selector="RM_10_1",
        columns={"Wert1", "Wert2" },
        criteria={
            EleID="[BezID1]",
            Wert2={"Kinderzimmer", "Wohnzimmer"}
        }
    },
    {
        -- Regel 3: Berechne Variablen myAlias und Wert1 mit Formeln aus dem letzten Ergebnis
        type="Calculate",
        formulas={
            { field="myAlias", formula="[Wert1] * 200" },
            { field="Wert1", formula="[myAlias] * 2" }
        }
    },
    {
        -- Regel 4: Summiere alle Werte in Spalte "Wert1" aus den übergebenen Daten der letzten Regel
        type="Summary",
        column="Wert1"
    }
}

return hvm.quantity.getValueByRules(Problem2)

Die NOT IN - Lösung

--- Hier Raum ändern
local Raum = {"60","70","140"}
-----------------------------------------------------------------
-- "190" Abstellraum
-- "180" Ankleide
-- "160" Arbeiten
--  "60" Bad 
-- "800" Balkon
-- "170" Büro
-- "20" Essen
-- "999" Abdichtung
-- "45" Flur
-- "220" Galerie
-- "290" Garage
-- "120" Gästezimmer
-- "140" Hauswirtschaftsraum
-- "210" Heizraum
-- "300" Keller
-- "90" Kinderzimmer
-- "30" Küche
-- "280" Loggia
-- "950" Ohne Berechnung
-- "948" Pflastern
-- "242" Sauna
-- "100" Schlafen
-- "150" Speiß
-- "270" Stauraum
-- "230" Studio
-- "211" Technik
-- "940" Terrasse
-- "200" Versorgungsraum
-- "80" WC
-- "70" WC/Dusche
-- "210" Werkstatt
-- "50" Windfang
-- "938" Winkelsteine
-- "240" Wintergarten
-- "10" Wohnzimmer
-- "130" Zimmer
-- "949" Gelände

--------------------------------------------------------------
local Ergebnis = {
    {
        type="Search",
        selector="DE_1_1",
        columns={"EleID" },
        criteria={ 
            Wert2={"Kellergeschoß","Erdgeschoß","Obergeschoß1","Obergeschoß2","Obergeschoß3","Dachgeschoß"},
            { field="Wert4", operator="<>", value="0.25" }
        }
    },
    {
        type="Search",
        selector="RM_13_0",
        columns={"Maß3"},
        groupBy={"EleID"},
        criteria={ 
            BezID2="[EleID]",
            --BTC=Raum
             { field="BTC", operator="NOT IN", value=Raum } 
        }
    },
    {
        type="Summary",
        column="Maß3"
    }
}

return hvm.quantity.getValueByRules(Ergebnis) * 0.15

Demonstration einer Regel mit dem Operator NOT IN.

Lösung - Einzelne Werte


--------------------------------------------------------------
local Regeln = {
    {
        type="Search",
        selector="DE_1_1",
        columns={"EleID" },
        criteria={
          Wert2={"Kellergeschoß","Erdgeschoß","Obergeschoß1","Obergeschoß2","Obergeschoß3","Dachgeschoß"},
          Wert4="0.25"
        }
    },
    {
        type="Search",
        selector="RM_13_1",
        columns={"BezID1"},
        groupBy={"EleID"},
        criteria={
            BezID2="[EleID]"
        }
    },
    {
        type="Search",
        selector="AW_2_1",
        columns={"Wert1","Maß1"},
        criteria={
            EleID="[BezID1]"
        }
    },
    {
        type="calculate",
        formulas={
            -- Multipliziert den Wert in Spalte "Wert1" mit 200 und schreibt das
            -- Ergebnis in das Feld "meinErgebnis"
            { field="meinErgebnis", formula="[Wert1] * [Maß1]" }
        }
    },
    {
        type="Summary",
        column={"meinErgebnis", "Wert1"},
        separate=true
    }
}

local ergebnis = hvm.quantity.getValueByRules(Regeln)

return ergebnis['meinErgebnis'] + ergebnis['Wert1']

Einzelne Werte aus dem Ergebnis abfragen und weiterverarbeiten.

Loch - Wand als Abzug

-- Hier Wandstärke ändern--------------------------
local Wandstaerke = "0.232"
---------------------------------------------------
---------------------------------------------------


local Loch_WS_Aussen = {
    {
        -- Suche LO_1_1 BezID5 (Id Wand an OK Loch)
        type="Search",
        selector="LO_1_1",
        columns={"BezID5"}, -- Nur Werte aus diesen Spalten zurückgeben
        groupBy={"BezID5"}
    },
    {
        -- Suche WS_1_1 BezID5 (Id Wand an OK Loch)und Feld E7 = 3
        type="Search",
        selector="WS_1_1",
        columns={"EleID","Maß1"}, -- Nur Werte aus diesen Spalten zurückgeben
        criteria={
            EleID="[BezID5]",
            E7="3",
            --E1="1"
             ["Maß1"]= Wandstaerke
         }
    },
    {
        -- Suche in LO_1_1(z.B.) die BezID5 mit dem Wert EleID von WS_1_1 
        type="Search",
        selector="Lo_1_1",
        columns={"Wert1"},
        criteria={
            BezID5="[EleID]"
        }

    },
    {
        -- Summiere alle Werte in Spalte "Wert1" aus den übergebenen Daten der letzten Regel
        type="Summary",
        column="Wert1"
    }
}

--Ziehe die Lochflächen der WS ausserhalb ab.
local wert = value
if wert ~= nil then
    local wert2 = wert - hvm.quantity.getValueByRules(Loch_WS_Aussen)
    return math.round(wert2,4)
end

Beispiel zur Abfrage von Positionen mit Abzug.

Ausgabe einer Excel-Datei


-- Pfad zur Excel-Datei
-- ACHTUNG: Die Datei muss sich im Verzeichnis "data/storage/content" befinden!
local ExcelFile = "data/storage/content/demo.xlsx"

-- ///// START - Generierung der Excel über LUA ///// --

local Workbook = require "xlsxwriter.workbook"

-- Create a workbook and add a worksheet.
local workbook  = Workbook:new(ExcelFile) -- Multitool / Pfad zur Excel-Datei hier angeben.

local worksheet = workbook:add_worksheet()

-- Some data we want to write to the worksheet.
local expenses = {
  {"Rent",  500},
  {"Gas",   200},
  {"Food",  300},
  {"Gym",   100},
}

-- Start from the first cell. Rows and columns are zero indexed.
local row = 0
local col = 0

-- Iterate over the data and write it out element by element.
for _, expense in ipairs(expenses) do
  local item, cost = unpack(expense)
  worksheet:write(row, col,     item)
  worksheet:write(row, col + 1, cost)
  row = row + 1
end

-- Write a total using a formula.
worksheet:write(row, 0, "Total")
worksheet:write(row, 1, "=SUM(B1:B4)")

workbook:close()

-- ///// ENDE / Generierung der Excel über LUA ///// --

-- Ausgabe der Excel-Datei in der Registerkarte "Excel-Ausgabe"
hvm.definition.outputExcelFile(ExcelFile)

Dieses Script erstellt mithilfe der Lua-Bibliothek xlsxwriter eine Excel-Datei auf dem Backend-Server und gibt die Datei für den Microsoft Office Live-Service frei, um diese im Frontend anzeigen zu lassen.

Wichtige Punkte die beachtet werden müssen:

  1. Der Pfad zur Excel-Datei muss im Lua-Script vollständig angegeben werden und die Datei muss sich im Verzeichnis data/storage/content befinden. Der Dateiname kann frei gewählt werden. Beachten sie allerdings, dass eine Datei mit dem gleichen Namen in unterschiedlichen Lua-Scripten überschrieben werden.
  2. Für die Erstellung der Excel-Datei kann jede Funktion der Bibliothek xlsxwriter.lua verwendet werden.
  3. Nachdem die Excel-Datei erstellt wurde, muss dem Multitool noch mitgeteilt werden, dass diese im Frontend angezeigt werden soll. Dies erfolgt mit dem Aufruf der Method hvm.definition.outputExcelFile() mit dem vollständigen Pfad zur Excel-Datei.

Ausgabe von Wandflächen

Rohdaten aus Scope


{
    "scope": {
        "Name_AW_Brutto_m2": {
            "0": {
                "BTC": "6",
                "EleID": "13755537496445",
                "Wert1": "6.03",
                "Ident_Text": "AW-14",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "1": {
                "BTC": "1",
                "EleID": "370354750941775",
                "Wert1": "34.8142",
                "Ident_Text": "AW-09",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "2": {
                "BTC": "2",
                "EleID": "70300314512232",
                "Wert1": "22.7542",
                "Ident_Text": "AW-10",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "3": {
                "BTC": "3",
                "EleID": "287370306862723",
                "Wert1": "10.69421",
                "Ident_Text": "AW-11",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "4": {
                "BTC": "4",
                "EleID": "153386182286982",
                "Wert1": "6.03",
                "Ident_Text": "AW-12",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "5": {
                "BTC": "5",
                "EleID": "134033976320153",
                "Wert1": "13.29615",
                "Ident_Text": "AW-13",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "6": {
                "BTC": "4",
                "EleID": "222679823843872",
                "Wert1": "0.48934",
                "Ident_Text": "AW-28",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "7": {
                "BTC": "7",
                "EleID": "516858567788146",
                "Wert1": "10.82385",
                "Ident_Text": "AW-15",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "8": {
                "BTC": "8",
                "EleID": "219448449041767",
                "Wert1": "22.7542",
                "Ident_Text": "AW-16",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "9": {
                "BTC": "1",
                "EleID": "70466266882342",
                "Wert1": "24.85804",
                "Ident_Text": "AW-17",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "10": {
                "BTC": "2",
                "EleID": "116508620345141",
                "Wert1": "22.13039",
                "Ident_Text": "AW-18",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "11": {
                "BTC": "3",
                "EleID": "88629450344157",
                "Wert1": "7.8312",
                "Ident_Text": "AW-19",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "12": {
                "BTC": "4",
                "EleID": "390790494528992",
                "Wert1": "6.03",
                "Ident_Text": "AW-20",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "13": {
                "BTC": "5",
                "EleID": "356314638578839",
                "Wert1": "13.29615",
                "Ident_Text": "AW-21",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "14": {
                "BTC": "6",
                "EleID": "146247729075274",
                "Wert1": "6.03",
                "Ident_Text": "AW-22",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "15": {
                "BTC": "7",
                "EleID": "305253496181486",
                "Wert1": "7.96085",
                "Ident_Text": "AW-23",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "16": {
                "BTC": "8",
                "EleID": "131117933083628",
                "Wert1": "22.13039",
                "Ident_Text": "AW-24",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "17": {
                "BTC": "1",
                "EleID": "423805779628839",
                "Wert1": "0",
                "Ident_Text": "AW-25",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "18": {
                "BTC": "2",
                "EleID": "522893299853861",
                "Wert1": "11.08631",
                "Ident_Text": "AW-26",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "19": {
                "BTC": "3",
                "EleID": "62304636646861",
                "Wert1": "0.0651",
                "Ident_Text": "AW-27",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "20": {
                "BTC": "5",
                "EleID": "462251810565972",
                "Wert1": "0.70275",
                "Ident_Text": "AW-29",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "21": {
                "BTC": "6",
                "EleID": "528206429683655",
                "Wert1": "0.48934",
                "Ident_Text": "AW-30",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "22": {
                "BTC": "7",
                "EleID": "216320708272555",
                "Wert1": "0.07939",
                "Ident_Text": "AW-31",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "23": {
                "BTC": "8",
                "EleID": "533004284464100",
                "Wert1": "11.08634",
                "Ident_Text": "AW-32",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "24": {
                "BTC": "9",
                "EleID": "460953056903346",
                "Wert1": "0.25245",
                "Ident_Text": "AW-33",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            },
            "25": {
                "BTC": "10",
                "EleID": "121567754794748",
                "Wert1": "0.25245",
                "Ident_Text": "AW-34",
                "Bezeichnung": "Außenwandflächen - in der Wandachse"
            }
        }
    },
    "Name_AW_Brutto_m2_Summe": 261.9665
}

Daten verarbeiten

local Wert_AW_Brutto_m2 = hvm.scope.get("Name_AW_Brutto_m2")
local Wert_AW_Brutto_m2_Summe = hvm.scope.get("Name_AW_Brutto_m2_Summe")

-- Pfad zur Excel-Datei
-- ACHTUNG: Die Datei muss sich im Verzeichnis "data/storage/content" befinden!
local ExcelFile = "data/storage/content/demo.xlsx"

-- ///// START - Generierung der Excel über LUA ///// --

local Workbook = require "xlsxwriter.workbook"

-- Erstellen einer Arbeitsmappe und eine Tabelle
local workbook  = Workbook:new(ExcelFile) -- Multitool / Pfad zur Excel-Datei hier angeben.
local worksheet = workbook:add_worksheet()

-- Breite der Spalte A auf 50 setzen
worksheet:set_column("A:A", 50)
-- Breite der Spalte B und C auf 10 setzen
worksheet:set_column("B:C", 10)
-- Breite der Spalte D auf 15 setzen
worksheet:set_column("D:D", 15)

-- Starten von erster Zelle aus. Zeilen und Spalten beginnen bei 0
local row = 0
local col = 0

-- Einzelne Positionen durchlaufen und in Zellen einfügen
for _, position in ipairs(Wert_AW_Brutto_m2) do
    -- Schreibe Werte als normaler Text in die aktuelle Zeile
    worksheet:write(row, col, position["Bezeichnung"])
    worksheet:write(row, col + 1, position["Ident_Text"])
    worksheet:write(row, col + 2, position["BTC"])
    -- Schreibe den Wert als Nummer in die Zelle
    worksheet:write_number(row, col + 3, position["Wert1"])

    -- Zähler für Zeilen um 1 erhöht um in nächste Zeile zu springen
    row = row + 1
end

-- Summe von Multitool einfügen
worksheet:write(row, 0, "Summe")
worksheet:write_number(row, col + 3, Wert_AW_Brutto_m2_Summe)

row = row + 1
-- Summe der Elemente über Excel berechnen
worksheet:write(row, 0, "Summe (Excel / Formel)")
worksheet:write_formula(row, 3, "=SUM(D1:D" .. (row - 1) .. ")")

workbook:close()

-- ///// ENDE / Generierung der Excel über LUA ///// --

-- Ausgabe der Excel-Datei in der Registerkarte "Excel-Ausgabe"
hvm.definition.outputExcelFile(ExcelFile)

Ein Besipiel um die einzelnen Wandflächen als Excel-Tabelle auszugeben.

Ergebnis:

multitool-excel-wandflaechen

lua