diff --git a/Use Cases/ExcelFlowChart/ExcelFlowChart.sln b/Use Cases/ExcelFlowChart/ExcelFlowChart.sln new file mode 100644 index 00000000..c33ecf80 --- /dev/null +++ b/Use Cases/ExcelFlowChart/ExcelFlowChart.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36109.1 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExcelFlowChart", "ExcelFlowChart\ExcelFlowChart.csproj", "{67EB8B15-C743-4D7E-9646-A8A31FB2266C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {67EB8B15-C743-4D7E-9646-A8A31FB2266C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {67EB8B15-C743-4D7E-9646-A8A31FB2266C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {67EB8B15-C743-4D7E-9646-A8A31FB2266C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {67EB8B15-C743-4D7E-9646-A8A31FB2266C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {6EF0B447-A3D4-4CBC-8489-B0847268873B} + EndGlobalSection +EndGlobal diff --git a/Use Cases/ExcelFlowChart/ExcelFlowChart/ExcelFlowChart.csproj b/Use Cases/ExcelFlowChart/ExcelFlowChart/ExcelFlowChart.csproj new file mode 100644 index 00000000..d3bc7ac6 --- /dev/null +++ b/Use Cases/ExcelFlowChart/ExcelFlowChart/ExcelFlowChart.csproj @@ -0,0 +1,14 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/Use Cases/ExcelFlowChart/ExcelFlowChart/Program.cs b/Use Cases/ExcelFlowChart/ExcelFlowChart/Program.cs new file mode 100644 index 00000000..36ad4bb0 --- /dev/null +++ b/Use Cases/ExcelFlowChart/ExcelFlowChart/Program.cs @@ -0,0 +1,230 @@ +using Syncfusion.XlsIO; +using Syncfusion.Drawing; + +/// +/// Builds an Order Fulfillment flowchart in an Excel worksheet using Syncfusion XlsIO. +/// +internal class Program +{ + /// + /// Entry point. Creates a workbook, draws the flowchart, applies colors, and saves the file. + /// + static void Main() + { + // Initialize ExcelEngine + using (ExcelEngine excelEngine = new ExcelEngine()) + { + // Use XLSX format by default + IApplication application = excelEngine.Excel; + application.DefaultVersion = ExcelVersion.Xlsx; + + // Create a new workbook with one worksheet + IWorkbook workbook = application.Workbooks.Create(1); + IWorksheet worksheet = workbook.Worksheets[0]; + + // Name & present the canvas + worksheet.Name = "Order Fulfillment Workflow"; + worksheet.IsGridLinesVisible = false; + + // ----- Shapes (row/col are 1-based anchors; height/width are in points) ----- + // Center column = 9, Right column = 14, as per your layout. + IShape start = AddFlowChartShape(worksheet, 2, 9, 50, 170, "Start", AutoShapeType.FlowChartTerminator); + IShape receiveOrder = AddFlowChartShape(worksheet, 6, 9, 50, 170, "Receive Order", AutoShapeType.FlowChartProcess); + IShape checkInv = AddFlowChartShape(worksheet, 10, 9, 50, 170, "Check Inventory", AutoShapeType.FlowChartProcess); + IShape invAvailable = AddFlowChartShape(worksheet, 14, 9, 50, 170, "Inventory Available?", AutoShapeType.FlowChartDecision); + + // No branch (left/vertical) + IShape noNotify = AddFlowChartShape(worksheet, 18, 9, 50, 170, "Notify Customer", AutoShapeType.FlowChartProcess); + IShape backOrCan = AddFlowChartShape(worksheet, 24, 9, 50, 170, "Backorder or Cancel", AutoShapeType.FlowChartProcess); + IShape leftEnd = AddFlowChartShape(worksheet, 30, 9, 50, 170, "End", AutoShapeType.FlowChartTerminator); + + // Yes branch (right/vertical) + IShape payment = AddFlowChartShape(worksheet, 14, 14, 50, 170, "Process Payment", AutoShapeType.FlowChartProcess); + IShape packed = AddFlowChartShape(worksheet, 18, 14, 50, 170, "Pack Order", AutoShapeType.FlowChartProcess); + IShape shipped = AddFlowChartShape(worksheet, 24, 14, 50, 170, "Ship Order", AutoShapeType.FlowChartProcess); + IShape yesNotify = AddFlowChartShape(worksheet, 30, 14, 50, 170, "Notify Customer", AutoShapeType.FlowChartProcess); + + // ----- Connectors ----- + // Decision → branches: fromSite/toSite mapping (0:Top, 1:Right, 2:Bottom, 3:Left) + Connect(worksheet, start, 2, receiveOrder, 0, true); + Connect(worksheet, receiveOrder, 2, checkInv, 0, true); + Connect(worksheet, checkInv, 2, invAvailable, 0, true); + Connect(worksheet, invAvailable, 1, payment, 3, true); + Connect(worksheet, invAvailable, 2, noNotify, 0, true); + + // Left chain (No branch) + Connect(worksheet, noNotify, 2, backOrCan, 0, true); + Connect(worksheet, backOrCan, 2, leftEnd, 0, true); + + // Right chain (Yes branch) + Connect(worksheet, payment, 2, packed, 0, true); + Connect(worksheet, packed, 2, shipped, 0, true); + Connect(worksheet, shipped, 2, yesNotify, 0, true); + Connect(worksheet, yesNotify, 3, leftEnd, 1, false); // Left to End; arrow at beginning to indicate flow into End + + // ----- Decision branch labels ----- + // "Yes" near the right-going branch from the decision + AddLabel(worksheet, 14, 12, "Yes"); + + // "No" near the downward branch from the decision + AddLabel(worksheet, 17, 9, "No"); + + // Colors + Color colorTerminator = ColorTranslator.FromHtml("#10B981"); // Emerald 500 + Color colorProcess = ColorTranslator.FromHtml("#3B82F6"); // Blue 500 + Color colorDecision = ColorTranslator.FromHtml("#F59E0B"); // Amber 500 + Color colorShip = ColorTranslator.FromHtml("#8B5CF6"); // Violet 500 + Color colorNotify = ColorTranslator.FromHtml("#14B8A6"); // Teal 500 + Color colorLine = ColorTranslator.FromHtml("#1F2937"); // Slate 800 (borders/connectors) + Color colorAccent = ColorTranslator.FromHtml("#2563EB"); // Blue 600 (reserved if needed) + + // Apply fills (lines are set in AddFlowChartShape) + start.Fill.ForeColor = colorTerminator; + receiveOrder.Fill.ForeColor = colorProcess; + checkInv.Fill.ForeColor = colorProcess; + invAvailable.Fill.ForeColor = colorDecision; + + noNotify.Fill.ForeColor = colorNotify; + backOrCan.Fill.ForeColor = colorNotify; + leftEnd.Fill.ForeColor = colorTerminator; + + payment.Fill.ForeColor = colorProcess; + packed.Fill.ForeColor = colorProcess; + shipped.Fill.ForeColor = colorShip; + yesNotify.Fill.ForeColor = colorNotify; + + // Save the workbook + string outputPath = Path.Combine(Environment.CurrentDirectory, "OrderFulfillmentFlowchart.xlsx"); + workbook.SaveAs(outputPath); + } + } + + /// + /// Adds a flowchart shape to at the given anchor. + /// + /// Target worksheet. + /// Top anchor row (1-based). + /// Left anchor column (1-based). + /// Shape height in points. + /// Shape width in points. + /// Caption rendered inside the shape. + /// Flowchart/auto shape type. + /// The created . + public static IShape AddFlowChartShape(IWorksheet worksheet, int row, int col, int height, int width, string text, AutoShapeType flowChartShapeType) + { + // Create the shape anchored at (row, col) + IShape flowChartShape = worksheet.Shapes.AddAutoShapes(flowChartShapeType, row, col, height, width); + + // Basic style + flowChartShape.Line.Weight = 1.25; + + // Content & alignment + flowChartShape.TextFrame.TextRange.Text = text; + flowChartShape.TextFrame.HorizontalAlignment = ExcelHorizontalAlignment.CenterMiddle; + flowChartShape.TextFrame.VerticalAlignment = ExcelVerticalAlignment.Middle; + + return flowChartShape; + } + + + /// + /// Adds a simple text label (transparent rectangle) for annotations such as "Yes"/"No". + /// + /// Target worksheet. + /// Top anchor row (1-based). + /// Left anchor column (1-based). + /// Label text. + /// The created label . + public static IShape AddLabel(IWorksheet worksheet, int row, int col, string text) + { + IShape rectangle = worksheet.Shapes.AddAutoShapes(AutoShapeType.Rectangle, row, col, 14, 40); + + // Make it text-only + rectangle.Fill.Transparency = 1f; + rectangle.Line.Visible = false; + + // Content & alignment + rectangle.TextFrame.TextRange.Text = text; + rectangle.TextFrame.HorizontalAlignment = ExcelHorizontalAlignment.CenterMiddle; + rectangle.TextFrame.VerticalAlignment = ExcelVerticalAlignment.Middle; + + // Nudge to the right to avoid overlapping connectors + rectangle.Left += 30; + + return rectangle; + } + + /// + /// Connects two shapes with a straight connector. + /// + /// Worksheet on which to draw the connector. + /// Start shape. + /// Connection site on start shape (0:Top, 1:Right, 2:Bottom, 3:Left). + /// End shape. + /// Connection site on end shape (0:Top, 1:Right, 2:Bottom, 3:Left). + /// If true, adds the arrow head at the end; otherwise at the beginning. + /// The created connector . + public static IShape Connect(IWorksheet worksheet, IShape from, int fromSite, IShape to, int toSite, bool isEnd) + { + // Absolute positions (in points) on the worksheet + PointF startPoint = GetConnectionPoint(from, fromSite); + PointF endPoint = GetConnectionPoint(to, toSite); + + // Bounding box for the straight connector + float left = Math.Min(startPoint.X, endPoint.X); + float top = Math.Min(startPoint.Y, endPoint.Y); + double width = Math.Abs(endPoint.X - startPoint.X); + double height = Math.Abs(endPoint.Y - startPoint.Y); + + // Draw a straight connector and place it + IShape connector = worksheet.Shapes.AddAutoShapes(AutoShapeType.StraightConnector, 1, 1, (int)height, (int)width); + connector.Left = (int)left; + connector.Top = (int)top; + + // Arrow style + if (isEnd) + connector.Line.EndArrowHeadStyle = ExcelShapeArrowStyle.LineArrow; + else + connector.Line.BeginArrowHeadStyle = ExcelShapeArrowStyle.LineArrow; + + connector.Line.Weight = 1.25; + return connector; + } + + /// + /// Computes a connection point (in points) on the boundary of for site indices: + /// 0 = Top, 1 = Right, 2 = Bottom, 3 = Left; any other value returns the center. + /// + /// The source shape. + /// Connection site index. + /// Absolute point coordinates (Left/Top in points) on the sheet where the connector should attach. + private static PointF GetConnectionPoint(IShape shape, int site) + { + float x = shape.Left; + float y = shape.Top; + + switch (site) + { + case 0: // Top + x += shape.Width / 2; + break; + case 1: // Right + x += shape.Width; + y += shape.Height / 2; + break; + case 2: // Bottom + x += shape.Width / 2; + y += shape.Height; + break; + case 3: // Left + y += shape.Height / 2; + break; + default: // Center + x += shape.Width / 2; + y += shape.Height / 2; + break; + } + + return new PointF(x, y); + } +}