| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843 |
- using DocumentFormat.OpenXml.Packaging;
- using DocumentFormat.OpenXml.Spreadsheet;
- using DocumentFormat.OpenXml;
- using System.Data;
- using System.Text.RegularExpressions;
- using Font = DocumentFormat.OpenXml.Spreadsheet.Font;
- using Color = DocumentFormat.OpenXml.Spreadsheet.Color;
- namespace qdr.app.studiou.orders2printpack.Labels
- {
- /// <summary>
- /// Generates Excel documents for printing labels using OpenXML format
- /// without relying on Microsoft Office libraries.
- /// </summary>
- public class ExcelLabelGenerator
- {
- // Default row height in points
- private const double DEFAULT_ROW_HEIGHT = 15.0;
- // Border styles
- private const int BORDER_STYLE_ID = 1;
- // Template pattern to match column names
- private static readonly Regex TemplatePattern = new Regex(@"\{([^{}]+)\}", RegexOptions.Compiled);
- // Formatting patterns
- private static readonly Regex BoldPattern = new Regex(@"\*\*(.+?)\*\*", RegexOptions.Compiled);
- private static readonly Regex ItalicPattern = new Regex(@"__(.+?)__", RegexOptions.Compiled);
- private static readonly Regex UnderlinePattern = new Regex(@"_(.+?)_", RegexOptions.Compiled);
- private static readonly Regex FontSizePattern = new Regex(@"\^\^(\d+)\^(.*?)\^\^", RegexOptions.Compiled);
- // Style indexes for different formatting
- private const int STYLE_NORMAL = 0;
- private const int STYLE_BORDER = 1;
- private const int STYLE_BOLD = 2;
- private const int STYLE_ITALIC = 3;
- private const int STYLE_UNDERLINE = 4;
- private const int STYLE_BOLD_BORDER = 5;
- private const int STYLE_ITALIC_BORDER = 6;
- private const int STYLE_UNDERLINE_BORDER = 7;
- // Font size style indexes start at 8 and go up
- private const int STYLE_FONT_SIZE_START = 8;
- /// <summary>
- /// Label format template that will be used to generate the content of each label.
- /// Use {columnName} placeholders to reference DataTable columns.
- /// Example: "ID: {ID}\nName: {ProductName}\nPrice: ${Price}"
- /// </summary>
- private readonly string _labelTemplate;
- /// <summary>
- /// Initializes a new instance of the ExcelLabelGenerator class with a specific label template.
- /// </summary>
- /// <param name="labelTemplate">Template string with {columnName} placeholders</param>
- public ExcelLabelGenerator(string labelTemplate)
- {
- _labelTemplate = labelTemplate ?? throw new ArgumentNullException(nameof(labelTemplate));
- }
- /// <summary>
- /// Initializes a new instance of the ExcelLabelGenerator class with a default template.
- /// The default template will simply concatenate all column values.
- /// </summary>
- public ExcelLabelGenerator()
- {
- _labelTemplate = string.Empty;
- }
- /// <summary>
- /// Generates an Excel document with labels formatted according to specified layout
- /// </summary>
- /// <param name="data">DataTable containing the label data</param>
- /// <param name="outputPath">Path where the Excel file will be saved</param>
- /// <param name="columnsPerPage">Number of label columns per A4 page</param>
- /// <param name="rowsPerPage">Number of label rows per A4 page</param>
- /// <param name="labelWidthPt">Width of each label in points</param>
- /// <param name="labelHeightPt">Height of each label in points</param>
- /// <returns>True if generation was successful, otherwise false</returns>
- public bool GenerateLabels(
- DataTable data,
- string outputPath,
- int columnsPerPage,
- int rowsPerPage,
- double labelWidthPt = 200.0,
- double labelHeightPt = 120.0)
- {
- if (data == null || data.Rows.Count == 0)
- throw new ArgumentException("Data table cannot be null or empty");
- if (columnsPerPage <= 0 || rowsPerPage <= 0)
- throw new ArgumentException("Columns and rows per page must be greater than zero");
- try
- {
- // Create the Excel document
- using (SpreadsheetDocument document = SpreadsheetDocument.Create(outputPath, SpreadsheetDocumentType.Workbook))
- {
- // Add a WorkbookPart to the document
- WorkbookPart workbookPart = document.AddWorkbookPart();
- workbookPart.Workbook = new Workbook();
- // Add styles to the workbook
- WorkbookStylesPart stylesPart = workbookPart.AddNewPart<WorkbookStylesPart>();
- stylesPart.Stylesheet = CreateStylesheet();
- stylesPart.Stylesheet.Save();
- // Add a WorksheetPart to the WorkbookPart
- WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
- worksheetPart.Worksheet = new Worksheet(new SheetData());
- // Add Sheets to the Workbook
- Sheets sheets = workbookPart.Workbook.AppendChild(new Sheets());
- // Add a Sheet to the Sheets collection
- Sheet sheet = new Sheet()
- {
- Id = workbookPart.GetIdOfPart(worksheetPart),
- SheetId = 1,
- Name = "Labels"
- };
- sheets.Append(sheet);
- // Get the SheetData from the WorksheetPart
- var sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();
- // Configure page layout for A4
- PageSetup pageSetup = new PageSetup
- {
- PaperSize = (UInt32Value)9U, // A4 paper size
- Orientation = OrientationValues.Portrait,
- FitToWidth = 1,
- FitToHeight = 0 // Auto height
- };
- PageMargins pageMargins = new PageMargins
- {
- Top = 0.75D,
- Bottom = 0.75D,
- Left = 0.7D,
- Right = 0.7D,
- Header = 0.3D,
- Footer = 0.3D
- };
- // Add page setup and margins
- worksheetPart.Worksheet.AppendChild(pageSetup);
- worksheetPart.Worksheet.AppendChild(pageMargins);
- // Set column widths based on the fixed label width
- Columns columns = new Columns();
- // Convert points to Excel column width
- // Excel column width units are based on the width of the "0" (zero) character in the default font
- // The conversion is approximate but works for most cases
- double excelColumnWidth = labelWidthPt / 7.0; // Approximate conversion
- for (int i = 1; i <= columnsPerPage; i++)
- {
- columns.Append(new Column
- {
- Min = (uint)i,
- Max = (uint)i,
- Width = excelColumnWidth,
- CustomWidth = true
- });
- }
- worksheetPart.Worksheet.InsertBefore(columns, sheetData);
- // Process each row of data
- Dictionary<uint, Row> rows = new Dictionary<uint, Row>();
- for (int dataIndex = 0; dataIndex < data.Rows.Count; dataIndex++)
- {
- // Calculate the label position on the page
- int pageCol = dataIndex % columnsPerPage + 1;
- int pageRow = dataIndex / columnsPerPage % rowsPerPage + 1;
- // Calculate actual row in Excel - one cell per label
- int excelRowIndex = dataIndex / columnsPerPage / rowsPerPage * rowsPerPage + pageRow;
- uint rowIndex = (uint)excelRowIndex;
- // Ensure row exists
- if (!rows.ContainsKey(rowIndex))
- {
- Row row = new Row
- {
- RowIndex = rowIndex,
- Height = labelHeightPt,
- CustomHeight = true
- };
- rows.Add(rowIndex, row);
- }
- string columnLetter = ColumnIndexToLetters(pageCol);
- // Create content for the label using the template with newlines
- string labelContent = GenerateLabelContent(data.Rows[dataIndex]);
- // Add cell with border style and content
- Cell cell = CreateCell(columnLetter, rowIndex, labelContent, BORDER_STYLE_ID);
- rows[rowIndex].Append(cell);
- }
- // Add all rows to the sheet
- foreach (var row in rows.Values.OrderBy(r => r.RowIndex))
- {
- sheetData?.Append(row);
- }
- // Save the worksheet
- worksheetPart.Worksheet.Save();
- // Save the workbook
- workbookPart.Workbook.Save();
- }
- return true;
- }
- catch (Exception ex)
- {
- Console.WriteLine($"Error generating Excel labels: {ex.Message}");
- return false;
- }
- }
- /// <summary>
- /// Gets or creates a style for a specific font size
- /// </summary>
- /// <param name="fontSize">Font size in points</param>
- /// <param name="withBorder">Whether to include a border</param>
- /// <returns>Style index</returns>
- private uint GetFontSizeStyle(int fontSize, bool withBorder)
- {
- // We'll use a simple formula to calculate the style index
- // STYLE_FONT_SIZE_START + (fontSize * 2) for no border
- // STYLE_FONT_SIZE_START + (fontSize * 2) + 1 for with border
- int styleOffset = fontSize * 2 + (withBorder ? 1 : 0);
- uint styleIndex = (uint)(STYLE_FONT_SIZE_START + styleOffset);
- // Return the style index - we'll ensure the style exists when creating the stylesheet
- return styleIndex;
- }
- /// <summary>
- /// Parses text for style markers and removes them from the text
- /// Handles nested formatting (e.g. _**text**_ for bold and underlined)
- /// </summary>
- /// <param name="text">Text to parse, will be modified to remove markers</param>
- /// <returns>TextStyle object with detected formatting</returns>
- private TextStyle ParseTextStyle(ref string text)
- {
- TextStyle style = new TextStyle();
- bool madeChanges;
- // We need to repeat the pattern matching until no more changes are made
- // This handles nested formatting like _**text**_
- do
- {
- madeChanges = false;
- // Check for bold
- if (BoldPattern.IsMatch(text))
- {
- style.IsBold = true;
- string newText = BoldPattern.Replace(text, "$1");
- if (newText != text)
- {
- text = newText;
- madeChanges = true;
- }
- }
- // Check for italic
- if (ItalicPattern.IsMatch(text))
- {
- style.IsItalic = true;
- string newText = ItalicPattern.Replace(text, "$1");
- if (newText != text)
- {
- text = newText;
- madeChanges = true;
- }
- }
- // Check for underline
- if (UnderlinePattern.IsMatch(text))
- {
- style.IsUnderlined = true;
- string newText = UnderlinePattern.Replace(text, "$1");
- if (newText != text)
- {
- text = newText;
- madeChanges = true;
- }
- }
- } while (madeChanges);
- return style;
- }
- /// <summary>
- /// Represents text formatting style
- /// </summary>
- private class TextStyle
- {
- public bool IsBold { get; set; }
- public bool IsItalic { get; set; }
- public bool IsUnderlined { get; set; }
- public bool HasFormatting => IsBold || IsItalic || IsUnderlined;
- }
- /// <summary>
- /// The key update is to the CreateCell method and ensuring all cell formats
- /// have WrapText = true properly set. Also ensuring the alignment is properly
- /// applied to each cell format.
- /// </summary>
- private Cell CreateCell(string columnName, uint rowIndex, string text, uint? styleIndex = null)
- {
- // Create the cell
- Cell cell = new Cell
- {
- CellReference = $"{columnName}{rowIndex}",
- DataType = CellValues.InlineString,
- StyleIndex = styleIndex ?? STYLE_NORMAL
- };
- // Create the inline string that will hold our text with preserved formatting
- InlineString inlineString = new InlineString();
- // We need to handle each line of text separately while preserving the newlines
- string[] lines = text.Split(new[] { '\n' }, StringSplitOptions.None);
- for (int lineIndex = 0; lineIndex < lines.Length; lineIndex++)
- {
- string line = lines[lineIndex];
- // Check if this is not the first line, we need to add a line break
- if (lineIndex > 0)
- {
- // For line breaks in Excel, we need to add a line feed character
- // within the same text run, not as a separate Break element
- Run lineBreakRun = new Run();
- lineBreakRun.AppendChild(new Text
- {
- Text = "\n",
- Space = SpaceProcessingModeValues.Preserve
- });
- inlineString.AppendChild(lineBreakRun);
- }
- // Process the current line
- // This can contain formatting markers like bold, italic, etc.
- string remainingText = line;
- // First check for font size formatting
- while (FontSizePattern.IsMatch(remainingText))
- {
- Match match = FontSizePattern.Match(remainingText);
- // Add text before the font size marker if any
- if (match.Index > 0)
- {
- string beforeText = remainingText.Substring(0, match.Index);
- TextStyle beforeStyle = ParseTextStyle(ref beforeText);
- AddFormattedRun(inlineString, beforeText, beforeStyle);
- }
- // Handle the font-sized text
- int fontSize;
- if (int.TryParse(match.Groups[1].Value, out fontSize))
- {
- string fontSizeText = match.Groups[2].Value;
- TextStyle fontSizeStyle = ParseTextStyle(ref fontSizeText);
- // Create a run with font size and any other formatting
- Run fontSizeRun = new Run();
- RunProperties fontSizeProps = new RunProperties();
- fontSizeProps.AppendChild(new FontSize { Val = fontSize });
- if (fontSizeStyle.IsBold)
- fontSizeProps.AppendChild(new Bold());
- if (fontSizeStyle.IsItalic)
- fontSizeProps.AppendChild(new Italic());
- if (fontSizeStyle.IsUnderlined)
- fontSizeProps.AppendChild(new Underline { Val = UnderlineValues.Single });
- fontSizeRun.AppendChild(fontSizeProps);
- fontSizeRun.AppendChild(new Text
- {
- Text = fontSizeText,
- Space = SpaceProcessingModeValues.Preserve
- });
- inlineString.AppendChild(fontSizeRun);
- }
- // Move past the processed part
- remainingText = remainingText.Substring(match.Index + match.Length);
- }
- // Process any remaining text in this line if any
- if (!string.IsNullOrEmpty(remainingText))
- {
- TextStyle remainingStyle = ParseTextStyle(ref remainingText);
- AddFormattedRun(inlineString, remainingText, remainingStyle);
- }
- }
- cell.AppendChild(inlineString);
- return cell;
- }
- /// <summary>
- /// Helper method to add a run with the specified formatting
- /// </summary>
- private void AddFormattedRun(InlineString inlineString, string text, TextStyle style)
- {
- if (string.IsNullOrEmpty(text))
- return;
- Run run = new Run();
- if (style.HasFormatting)
- {
- RunProperties props = new RunProperties();
- if (style.IsBold)
- props.AppendChild(new Bold());
- if (style.IsItalic)
- props.AppendChild(new Italic());
- if (style.IsUnderlined)
- props.AppendChild(new Underline { Val = UnderlineValues.Single });
- run.AppendChild(props);
- }
- run.AppendChild(new Text
- {
- Text = text,
- Space = SpaceProcessingModeValues.Preserve
- });
- inlineString.AppendChild(run);
- }
- /// <summary>
- /// This is a key modification to ensure ALL cell formats have WrapText=true
- /// </summary>
- private Stylesheet CreateStylesheet()
- {
- Stylesheet stylesheet = new Stylesheet();
- // Create Fonts
- Fonts fonts = new Fonts();
- // Font 0: Normal (11pt)
- Font normalFont = new Font();
- normalFont.AppendChild(new FontSize { Val = 11D });
- fonts.Append(normalFont);
- // Font 1: Bold (11pt)
- Font boldFont = new Font();
- boldFont.AppendChild(new FontSize { Val = 11D });
- boldFont.Append(new Bold());
- fonts.Append(boldFont);
- // Font 2: Italic (11pt)
- Font italicFont = new Font();
- italicFont.AppendChild(new FontSize { Val = 11D });
- italicFont.Append(new Italic());
- fonts.Append(italicFont);
- // Font 3: Underline (11pt)
- Font underlineFont = new Font();
- underlineFont.AppendChild(new FontSize { Val = 11D });
- underlineFont.Append(new Underline() { Val = UnderlineValues.Single });
- fonts.Append(underlineFont);
- // Add font sizes from 8pt to 72pt
- for (int size = 8; size <= 72; size++)
- {
- // Regular font with custom size
- Font sizedFont = new Font();
- sizedFont.AppendChild(new FontSize { Val = (double)size });
- fonts.Append(sizedFont);
- }
- fonts.Count = (uint)fonts.ChildElements.Count;
- // Create Fills
- Fills fills = new Fills();
- Fill fill1 = new Fill();
- fill1.PatternFill = new PatternFill { PatternType = PatternValues.None };
- Fill fill2 = new Fill();
- fill2.PatternFill = new PatternFill { PatternType = PatternValues.Gray125 };
- fills.Append(fill1);
- fills.Append(fill2);
- fills.Count = (uint)fills.ChildElements.Count;
- // Create Borders
- Borders borders = new Borders();
- // Border 0: No border
- Border noBorder = new Border();
- borders.Append(noBorder);
- // Border 1: All sides
- Border allBorder = new Border();
- // Left Border
- LeftBorder leftBorder = new LeftBorder { Style = BorderStyleValues.Thin };
- leftBorder.Append(new Color { Auto = true });
- allBorder.Append(leftBorder);
- // Right Border
- RightBorder rightBorder = new RightBorder { Style = BorderStyleValues.Thin };
- rightBorder.Append(new Color { Auto = true });
- allBorder.Append(rightBorder);
- // Top Border
- TopBorder topBorder = new TopBorder { Style = BorderStyleValues.Thin };
- topBorder.Append(new Color { Auto = true });
- allBorder.Append(topBorder);
- // Bottom Border
- BottomBorder bottomBorder = new BottomBorder { Style = BorderStyleValues.Thin };
- bottomBorder.Append(new Color { Auto = true });
- allBorder.Append(bottomBorder);
- // Diagonal Border (blank)
- allBorder.Append(new DiagonalBorder());
- borders.Append(allBorder);
- borders.Count = (uint)borders.ChildElements.Count;
- // Create CellFormats
- CellFormats cellFormats = new CellFormats();
- // *** CRITICALLY IMPORTANT: All cell formats must have WrapText=true ***
- // Format 0: Default / Normal
- CellFormat format0 = new CellFormat
- {
- NumberFormatId = 0,
- FontId = 0,
- FillId = 0,
- BorderId = 0,
- FormatId = 0,
- ApplyAlignment = true
- };
- format0.AppendChild(new Alignment
- {
- Vertical = VerticalAlignmentValues.Center,
- Horizontal = HorizontalAlignmentValues.Left,
- WrapText = true,
- Indent = 1, // Left indent for text margin
- JustifyLastLine = false
- });
- cellFormats.Append(format0);
- // Format 1: Border only
- CellFormat format1 = new CellFormat
- {
- NumberFormatId = 0,
- FontId = 0,
- FillId = 0,
- BorderId = 1,
- FormatId = 0,
- ApplyBorder = true,
- ApplyAlignment = true
- };
- format1.AppendChild(new Alignment
- {
- Vertical = VerticalAlignmentValues.Center,
- Horizontal = HorizontalAlignmentValues.Left,
- WrapText = true,
- Indent = 1, // Left indent for text margin
- JustifyLastLine = false
- });
- cellFormats.Append(format1);
- // Format 2: Bold
- CellFormat format2 = new CellFormat
- {
- NumberFormatId = 0,
- FontId = 1,
- FillId = 0,
- BorderId = 0,
- FormatId = 0,
- ApplyFont = true,
- ApplyAlignment = true
- };
- format2.AppendChild(new Alignment
- {
- Vertical = VerticalAlignmentValues.Center,
- Horizontal = HorizontalAlignmentValues.Left,
- WrapText = true,
- Indent = 1, // Left indent for text margin
- JustifyLastLine = false
- });
- cellFormats.Append(format2);
- // Format 3: Italic
- CellFormat format3 = new CellFormat
- {
- NumberFormatId = 0,
- FontId = 2,
- FillId = 0,
- BorderId = 0,
- FormatId = 0,
- ApplyFont = true,
- ApplyAlignment = true
- };
- format3.AppendChild(new Alignment
- {
- Vertical = VerticalAlignmentValues.Center,
- Horizontal = HorizontalAlignmentValues.Left,
- WrapText = true,
- Indent = 1, // Left indent for text margin
- JustifyLastLine = false
- });
- cellFormats.Append(format3);
- // Format 4: Underline
- CellFormat format4 = new CellFormat
- {
- NumberFormatId = 0,
- FontId = 3,
- FillId = 0,
- BorderId = 0,
- FormatId = 0,
- ApplyFont = true,
- ApplyAlignment = true
- };
- format4.AppendChild(new Alignment
- {
- Vertical = VerticalAlignmentValues.Center,
- Horizontal = HorizontalAlignmentValues.Left,
- WrapText = true,
- Indent = 1, // Left indent for text margin
- JustifyLastLine = false
- });
- cellFormats.Append(format4);
- // Format 5: Bold + Border
- CellFormat format5 = new CellFormat
- {
- NumberFormatId = 0,
- FontId = 1,
- FillId = 0,
- BorderId = 1,
- FormatId = 0,
- ApplyFont = true,
- ApplyBorder = true,
- ApplyAlignment = true
- };
- format5.AppendChild(new Alignment
- {
- Vertical = VerticalAlignmentValues.Center,
- Horizontal = HorizontalAlignmentValues.Left,
- WrapText = true,
- Indent = 1, // Left indent for text margin
- JustifyLastLine = false
- });
- cellFormats.Append(format5);
- // Format 6: Italic + Border
- CellFormat format6 = new CellFormat
- {
- NumberFormatId = 0,
- FontId = 2,
- FillId = 0,
- BorderId = 1,
- FormatId = 0,
- ApplyFont = true,
- ApplyBorder = true,
- ApplyAlignment = true
- };
- format6.AppendChild(new Alignment
- {
- Vertical = VerticalAlignmentValues.Center,
- Horizontal = HorizontalAlignmentValues.Left,
- WrapText = true,
- Indent = 1, // Left indent for text margin
- JustifyLastLine = false
- });
- cellFormats.Append(format6);
- // Format 7: Underline + Border
- CellFormat format7 = new CellFormat
- {
- NumberFormatId = 0,
- FontId = 3,
- FillId = 0,
- BorderId = 1,
- FormatId = 0,
- ApplyFont = true,
- ApplyBorder = true,
- ApplyAlignment = true
- };
- format7.AppendChild(new Alignment
- {
- Vertical = VerticalAlignmentValues.Center,
- Horizontal = HorizontalAlignmentValues.Left,
- WrapText = true,
- Indent = 1, // Left indent for text margin
- JustifyLastLine = false
- });
- cellFormats.Append(format7);
- cellFormats.Count = (uint)cellFormats.ChildElements.Count;
- // Add additional cell formats for font sizes 8pt to 72pt
- // Both with and without borders
- for (int size = 8; size <= 72; size++)
- {
- int fontIndex = 4 + (size - 8); // Font indexes start after our 4 basic fonts
- // Create style without border
- CellFormat formatSize = new CellFormat
- {
- NumberFormatId = 0,
- FontId = (uint)fontIndex,
- FillId = 0,
- BorderId = 0,
- FormatId = 0,
- ApplyFont = true,
- ApplyAlignment = true
- };
- formatSize.AppendChild(new Alignment
- {
- Vertical = VerticalAlignmentValues.Center,
- Horizontal = HorizontalAlignmentValues.Left,
- WrapText = true,
- Indent = 1,
- JustifyLastLine = false
- });
- cellFormats.Append(formatSize);
- // Create style with border
- CellFormat formatSizeBorder = new CellFormat
- {
- NumberFormatId = 0,
- FontId = (uint)fontIndex,
- FillId = 0,
- BorderId = 1,
- FormatId = 0,
- ApplyFont = true,
- ApplyBorder = true,
- ApplyAlignment = true
- };
- formatSizeBorder.AppendChild(new Alignment
- {
- Vertical = VerticalAlignmentValues.Center,
- Horizontal = HorizontalAlignmentValues.Left,
- WrapText = true,
- Indent = 1,
- JustifyLastLine = false
- });
- cellFormats.Append(formatSizeBorder);
- }
- cellFormats.Count = (uint)cellFormats.ChildElements.Count;
- stylesheet.Append(fonts);
- stylesheet.Append(fills);
- stylesheet.Append(borders);
- stylesheet.Append(cellFormats);
- return stylesheet;
- }
- /// <summary>
- /// Generates the content for a label based on the template and data row
- /// </summary>
- /// <param name="dataRow">The DataRow containing the label data</param>
- /// <returns>String representing the label content with newlines</returns>
- private string GenerateLabelContent(DataRow dataRow)
- {
- string result;
- if (string.IsNullOrEmpty(_labelTemplate))
- {
- // Default behavior: use column name and value for each column
- List<string> lines = new List<string>();
- foreach (DataColumn column in dataRow.Table.Columns)
- {
- object value = dataRow[column.ColumnName];
- string lineContent = $"{column.ColumnName}: {(value != DBNull.Value ? value?.ToString() : string.Empty)}";
- lines.Add(lineContent);
- }
- result = string.Join("\n", lines);
- }
- else
- {
- // Use the specified template
- result = _labelTemplate;
- // Replace all column placeholders with actual values
- result = TemplatePattern.Replace(result, match =>
- {
- string columnName = match.Groups[1].Value;
- if (dataRow.Table.Columns.Contains(columnName))
- {
- object value = dataRow[columnName];
- return value != DBNull.Value ? value?.ToString() ?? string.Empty : string.Empty;
- }
- return match.Value; // Keep the placeholder if column not found
- });
- }
- return result;
- }
- /// <summary>
- /// Converts a column index to Excel column letters (e.g., 1 = A, 27 = AA)
- /// </summary>
- private string ColumnIndexToLetters(int columnIndex)
- {
- string columnLetters = string.Empty;
- while (columnIndex > 0)
- {
- int remainder = (columnIndex - 1) % 26;
- columnLetters = (char)('A' + remainder) + columnLetters;
- columnIndex = (columnIndex - 1) / 26;
- }
- return columnLetters;
- }
- }
- }
|