DataMatrix- Code generieren pro Seite

Hallo zusammen,

Ich habe in meinem Report eine Tabelle, deren Zeilen sich über mehrere Seiten erstrecken.
Auf jeder Seite sollen in einer DataMatrix Informationen der Zeilen auf der jeweiligen Seite angezeigt werden. Das Problem, welches ich habe ist, dass ich nicht vorher weiß welche / wie viele Zeilen auf der jeweiligen Seite aufgedruckt werden, da jede Zeile eine unterschiedliche Höhe haben kann.
Habt ihr Vorschläge wie ich mein Problem lösen könnte?

Vielen Dank für Tipps.

Gruß

Christoph

Hallo Christoph und herzlich willkommen hier im Forum :slight_smile:.

Kannst du uns Details geben, welche Informationen im DataMatrix erscheinen sollen? Ein paar Screenshots mit genaueren Erläuterungen wären sehr hilfreich. Generell kann sich der Inhalt eines Barcodes z. B. auch per Formel ergeben. Mit GetVar und SetVar kann man sich Werte merken oder aggregieren und die dann auch wieder auslesen. Aber ohne genauere Informationen wäre es geraten.

Danke für die Antwort,

Ich bin dabei den bundeseinheitlichen Medikationsplan umzusetzen. Die Datamatrix ist hierbei auf jeder Seite eine andere. Inhalt des Codes, in Form von XML, ist jedoch immer die Daten der austellenden Partei und die Patientendaten. Was bei jeder Seite unterschiedlich ist, sind logischerweise die Sektionen (“Verblistert” / “Nicht Verblistert” s. Beispielbilder) und die dazugehörigen Medikamente.

Im Code sollen von der Medikation die Pharmazentralnummer, die Einnahmezeitpunkte, Hinweise, sowie Zusatzinformationen der Medikationen gespeichert werden. Für meine Zwecke genügt es jedoch nur zu wissen auf welcher Seite sich jede Zeile der Tabelle sich befindet.

Gruß

Christoph

anbei noch die zweite Seite und ein XML Beispiel-Code.

<?xml version="1.0" encoding="utf-8"?>
<MP xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" v="2.0.6">
  <P g="Fritz" f="Moped" b="16.10.1939" s="M" />
  <A s="Marktplatz 5" z="63445" c="Heinrichsdorf" p="01522735678" t="08.12.2023" />
  


  //dieser Block stellt den dynamischen Teil der XML-Datei dar
  
  
  <S t="Verblisterbar">
    <M p="16033349" du="1" i="Für das Medikament liegt eine Einnahmepause vom 28.11.2023 bis zum 07.12.2023 vor. Das Medikament soll nach dem Essen verabreicht werden. " r="Diabetes"/>
    <M p="69693" du="1" i="Das Medikament soll nach dem Essen verabreicht werden. Medikament soll alle 4 Tage verabreicht werden. Im Wasser auflösen. " r="Herzrhythmus-Störung"/>
    <M p="89945" du="1" i="Das Medikament wird nach einem Wochenschema verabreicht. Tablette zerkauen. " r="Blutzucker" x="Mo: 0-1-0-0-0-0-0-0. Di: 0-0-1-0-0-0-0-0. Mi: 0-0-0-1-0-0-0-0. So: 0-0-0-0-0-1-0-1. "/>
    <M p="14120" du="1" i="Das Medikament soll nur bis zum 14.12.2023 verabreicht werden. Das Medikament wird 4 Tage lang verabreicht. Dannach wiederholt sich der 4-Tagesrhythmus noch 6 mal (zyklische Dosierung). Startdatum: 21.11.2023. Tablette lutschen. " r="Hypertonie" x="Tag 1: 0-2-0-0-0-3-0-0. Tag 2: 0-1-0-0-0-1-0-0. Tag 3: 0-0-0-0-1-0-0-0. Tag 4: 0-0-0-0-0-1-0-0. "/>
    <M p="11295470" du="1" i="" r="Hämorrhoiden"/>
    <M p="2204439" du="1" i="Medikament soll alle 3 Tage verabreicht werden. "/>   
  </S>
  <S t="Nicht Verblisterbar" >
    <M p="6998784" du="1" i="Medikament soll jede Stunde 1 mal verabreicht werden. " r="Knieschmerzen"/>
    <M p="2801069" du="1" i="" r="Unterzuckerung"/>
    <M p="3737617" du="1" i="Medikament soll alle 3 Stunden 2 mal verabreicht werden. " r="Hautausschlag Bein"/>	
  </S>



</MP>

Das klingt spannend. In dem Fall würde ich den DataMatrix-Barcode zeitlich mit der Tabelle verketten, so dass immer erst die Tabelle, dann der Barcode gedruckt wird. Du kannst das auch über die Objektliste hinbekommen, indem du da die richtige Reihenfolge wählst. Ansonsten ist das hier dokumentiert: Die “zeitliche” Verkettung.

Im nächsten Schritt musst du wissen, welche Zeilen auf der aktuellen Seite gedruckt wurden. Dafür könntest du das AutoDefineField Ereignis verwenden. Da kommt jedes Feld vorbei, das für die Tabelle angemeldet wird, also z. B. auch die PZN-Nummer. Die kannst du dir in einer Liste o. ä. merken.

Dann würde ich das DrawObject Ereignis verwenden um herauszufinden, wann die Tabelle auf der aktuellen Seite beendet wird (wenn IsBeforePaint für die Tabelle false liefert).

In diesem Moment wird direkt danach der DataMatrix ausgegeben. Dann könnte es möglich sein, die XML-Datei wie benötigt aufzubereiten (welche Daten benötigt werden weißt du ja dann) und per (sender as ListLabel).Variables.Add() zu übergeben. Oder du verwendest im DataMatrix gleich die LoadFile$-Funktion für den Inhalt und sorgst im Event dafür, dass das richtige XML mit dem richtigen Inhalt erzeugt wird.

Das habe ich jetzt so nicht ausprobieren können, schau doch mal ob das schon was hilft und melde dich sonst gerne wieder hier.

Vielen Dank für die Antwort,

ich habe die Vorschläge versucht umzusetzen. Es funktioniert jedoch noch nicht ganz. Irgendwie erfasst er die neuen Seiten falsch. In meinem Beispiel sind fünf Medikamente auf der ersten Seite und vier auf der zweiten Seite. IsBeforePaint wird aber nach dem ersten, und siebenten Medikament ausgelöst. Das macht aus meiner Perspektive keinen Sinn.
Vielleicht habe ich auch mit dem Code etwas falsch verstanden. Hier ist der Auszug:

var IsNewPage = false;
var pznListOnPage = new List<int>();
var pageDataMatrixList = new List<string>();
ll.AutoDefineField += (s, e) =>
{
    var name = e.AssociatedTableRow.Columns.FirstOrDefault(x => x.ColumnName == "Pzn");

    if (name != null && !pznListOnPage.Contains((int)name.Content))
        pznListOnPage.Add((int)name.Content);
};

ll.DrawObject += (s, e) =>
{
    if (e.IsBeforePaint == false && e.ObjectType == LlObjectType.Table)
    {
        IsNewPage = true;
        pageDataMatrixList.Add(MedicationPlanHelper.GetXMLString(this.SelectedPatient, pznListOnPage, medicationPlanStart, medicationPlanEnd, Pharmacy));
    }
};

Gruß

Christoph

Hallo Christoph,

wir haben mal Folgendes als Beispiel zusammengestellt:

Für jede Seite wird eine ContentsPrinted-Variable mit der Liste der Firmennamen gefüllt, die auf dieser Seite gedruckt werden sollen:

Der Code dazu sieht so aus:

List<string> _passedFields = new List<string>();
string _lastCompany = null;
int? _expectedNumberOfRecords = null;
int _actualNumberOfRecords = 0;

using (LL)
{
    LL.Variables.Add("ContentsPrinted", "");
    LL.AutoDefineField += (s, ea) =>
    {
        if (!ea.IsDesignMode)
        {
            if (!_expectedNumberOfRecords.HasValue)
            {
                _expectedNumberOfRecords = ((s as ListLabel).DataSource as IDataProvider).GetTable(ea.AssociatedTableRow.TableName).Count;
            }
            if (ea.Name == "Customers.CompanyName")
            {
                _actualNumberOfRecords++;
                if (_lastCompany != null)
                {
                    _passedFields.Add(_lastCompany);
                }
                string content = ((ea.Value == System.DBNull.Value) ? "(null)" : (string)ea.Value);
                _lastCompany = content;
                if (_actualNumberOfRecords == _expectedNumberOfRecords)
                {
                    _passedFields.Add(content);
                }
            }
        }
    };
    LL.DrawObject += (s, ea) =>
    {
        if (ea.IsBeforePaint == false && ea.ObjectType == LlObjectType.Table)
        {
            if (ea.ObjFinished.HasValue && ea.ObjFinished.Value)
                _passedFields.Add(_lastCompany);
            (s as ListLabel).Variables.Add("ContentsPrinted", String.Join(",", _passedFields));
            _passedFields.Clear();
        }
    };
    LL.Print();
}  

Die Variable kann natürlich auch an ein Barcode-Objekt übergeben werden.

Es geht sicher noch besser :slightly_smiling_face:, aber ich hoffe dass hilft dir erstmal weiter.

1 Like

Using libraries such as python datamatrix or zint barcode generator in your preferred programming language, you can dynamically generate datamatrix codes for each page. Adapt the code to parse table data per page and generate datamatrix codes based on the data while dealing with variable row heights.

Also das hat jetzt geklappt.
Das Problem, welches ich jetzt habe, ist dass es das letzte Medikament (von der letzten Seite) an erster Stelle auf der ersten Seite anzeigt.


(zur Veranschaulichung wurden die Medikamentennamen einfach als Text eingefügt statt in der Datamatrix)

Hier noch der entsprechende Codeausschnitt:

var _currentPZN = new List<string>();
string _lastPZN = null;
int? _expectedNumberOfRecords = null;
int _actualNumberOfRecords = 0;
ll.AutoDefineField += (s, e) =>
    {
        if (!e.IsDesignMode)
        {
            if(e.Name == "Medications.Arzneimittel")
            {
                if (!_expectedNumberOfRecords.HasValue)
                {
                    _expectedNumberOfRecords = medicationsDataTable.Rows.Count;
                }
                _actualNumberOfRecords++;
                if(_lastPZN != null)
                    _currentPZN.Add(_lastPZN);
                string content = (e.Value == System.DBNull.Value) ? "(null)" : Convert.ToString(e.Value);
                _lastPZN = content;
                if (_actualNumberOfRecords == _expectedNumberOfRecords)
                    _currentPZN.Add(content);
            }
        }
    };
ll.DrawObject += (s, e) =>
{ 
    if (e.IsBeforePaint == false && e.ObjectType == LlObjectType.Table)
    {
        if (e.ObjFinished.HasValue && e.ObjFinished.Value)
            _currentPZN.Add(_lastPZN);
        // ToDo:
        // übergabe der Liste an XML Builder
        (s as ListLabel).Variables.Add("ContentsPrinted", String.Join(",", _currentPZN));
        if (_actualNumberOfRecords == _expectedNumberOfRecords)
            _currentPZN.Add(_lastPZN)

        _currentPZN.Clear();
    }

};

Der einzige sichtbare Unterschied ist, dass die Variable ContentsPrinted beim AutoDefineField-Ereignis nicht hinzugefügt wird. Könnte das nochmal getestet werden?

Ansonsten benötigen wir für weitere Analysen bitte ein absolut minimiertes, lauffähiges Sourcecode-Sample, mit dem wir das Problem reproduzieren können.

Hierzu gerne über das Supportportal auf uns zukommen.