I tried to implement bubble sort in BICMD by phoenetic string comparison turned out not to be supported
But for my use case a method to group a 2D array of string by first key would do fine
/* ----------------------------------------------------------------
Peter Lykkegaard, 25 Oct 2025
-----------------------------
Name: groupByArray
Description
This code processes a 2D array "pvData$[][]" by grouping rows based on the value in the first column.
It avoids reprocessing rows by marking them as "found" in "lvProcessedRows$[]".
The grouped rows are stored in "lvGroupedData$[][]", preserving all column data.
The algorithm uses nested loops to compare and group rows with matching keys.
Parameters
pvData$[][] - 2D array which should be grouped
Output
$[][] - 2D array grouped by keyword
-------------------------------------------------------------- */
local
lvTotalRows%, // Total number of rows in pvData$
lvColumnIndex%, // Index for iterating through columns
lvNewRowIndex%, // Index for inserting into lvGroupedData$
lvKeyIndex%, // Index for keyword for grouping
lvTotalColumns%, // Total number of columns in pvData$
lvCurrentRow%, // Current row being processed
lvCurrentKey$, // Key value from the first column of the current row
lvCheckRow%, // Row index used to check for matching keys
lvProcessedRows$[], // Array to track which rows have been processed
lvGroupedData$[][], // Output array to store grouped rows
lvFound$; // Marker string to indicate a row has been processed
copy 0 to lvKeyIndex%;
copy 0 to lvCurrentRow%;
copy 0 to lvNewRowIndex%;
copy "found" to lvFound$;
// Number of rows
copy getSize(pvData$) to lvTotalRows%;
// Depth / number of columns
copy getSize(pvData$[1]) to lvTotalColumns%;
// Outer loop: iterate through the array
for lvCurrentRow% = 0 to lvTotalRows% - 1
if (lvProcessedRows$[lvCurrentRow%] &!= lvFound$)
copy pvData$[lvCurrentRow%][lvKeyIndex%] to lvCurrentKey$;
// Inner loop: check all rows from current to end for matching keys
for lvCheckRow% = lvCurrentRow% to lvTotalRows% - 1
if (pvData$[lvCheckRow%][lvKeyIndex%] &= lvCurrentKey$)
traceln("lvCurrentKey: " & lvCurrentKey$);
for lvColumnIndex% = 0 TO lvTotalColumns% - 1
copy pvData$[lvCheckRow%][lvColumnIndex%] to lvGroupedData$[lvNewRowIndex%][lvColumnIndex%];
next
// Mark the row as processed and increment the index
// to examine the next row for grouping
copy lvFound$ to lvProcessedRows$[lvCheckRow%];
copy lvNewRowIndex% + 1 to lvNewRowIndex%;
endif
next
endif
next
// return array grouped by first given key
exitProc(lvGroupedData$);
Easily converted to NET 9 C# 12 using CoPilot / ChatGPT5, use what data content you'd prefer and run some iterations in a Console App to check program flow
An utility to add leading zeros up to given length to a numeric string
Please note Alphanumeric string will be left untouched
A procedure to use in Seeburger BIC Mapping Designer
It will extend your library for string handling
/* -----------------------------
Peter Lykkegaard, 22 mar 2019
-----------------------------
Method
zeroFill
Parameters
value$: String to prefix with zeros
Num%: Number of characters, length of string after prefixzing
Returns
$
Description
If the parameter value is a numeric value and
the length of the string does not exceed length of the value
*/
if (isNumeric(value$) && len(value$) < num%)
copy lfill(value$, "0", num%) to value$;
endif
exitProc(value$);
Split text on right most space before limit is reached
Use to split text on several lines in receiving document, eg edifact LIN-IMD-C273 has several 7008 text element
// -----------------------------
// Peter Lykkegaard, 22 mar 2019
// -----------------------------
// Split long note on right most space before limit is reached
// TODO! Check parameters if they are of valid type/content
//
// Name: splitNoteBySpace
// Description: Method to split a given string by latest space before length limit
// Parameters
// input$, alphanumerical / String which needs to be split
// max$, alphanumerical / Max characters on each line
// Output, alphanumeric / array / Array of strings to return
local lvOutput$[];
#importJavaStart
import java.util.regex.Matcher;
import java.util.regex.Pattern;
#importJavaEnd
#javastart
String input = _StrVar_PINPUT.getString();
int max = (int)_NumVar_PMAX.getNum();
int len = input.length();
String regex = "(.{1," + max + "})(?:\\s|$)";
Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
Matcher matcher = pattern.matcher(input);
_StrVar_LVOUTPUT.getJuVar(0, 2).setString(input);
if (len > max)
{
int idx = 0; // Entries in output
while (matcher.find()) {
for (int i = 1; i <= matcher.groupCount(); i++) {
_StrVar_LVOUTPUT.getJuVar(idx, 2).setString(matcher.group(i).toString());
}
idx++;
}
}
#javaEnd
exitProc(lvOutput$);
Edit IDOC document properties
Once the IDOC definition is imported in the Mapping Designer make sure to set Max Occurences on the document root (DC1)
Use unlimited (-1) or 9999
- IDOCs are send from SAP to a queue with append
- File is read and mapped to edifact
- The transaction set header is set in New Mapping and the footer in Mapping End as found in the additional programs (tpå of source message)
- For each document / message you can use New Message and Message End

An utility to retrieve current year
This is a procedure to use in Seeburger BIC Mapping Designer
/* -----------------------------
Peter Lykkegaard, 25 apr 2023
-----------------------------
procedure getUUID
Parameters:
None
Output
String
Get ramdom UUID
----------------------------- */
#importJavaStart
import java.util.UUID;
#importJavaEnd
local
lvOutput$;
#javastart
_StrVar_LVOUTPUT.setString(UUID.randomUUID().toString());
#javaend
exitProc(lvOutput$);