using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using GraphLibrary;
using GraphAlgorithms;
using OfficeOpenXml;
using System.IO;

namespace DistanzVektorAlgorithmusGenerator
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            graphControl1.Options |= GraphControl.DisplayOptions.ShowEdgeWeights;
#if DEBUG
            textBox1.Text = "Moritz\r\nLuka\r\nDavid\r\nLeander\r\nNico\r\nJoshua\r\nMonica\r\nHannes\r\nCaroline\r\nPaul\r\nSimon";
#endif
        }

        private void button1_Click(object sender, EventArgs ea)
        {
            graphControl1_NodeDoubleClicked(null, null);
            graphControl1.Graph = new Graph(false);
            string[] names = textBox1.Text.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            Random r = new Random();
            foreach (string s in names)
            {
                Node n = graphControl1.Graph.Nodes.Add(s);
                n.Color = Color.White;
                n.Position = new Point(r.Next(2 * graphControl1.NodeRadius, graphControl1.Width - graphControl1.NodeRadius * 4),
                                       r.Next(2 * graphControl1.NodeRadius, graphControl1.Height - 4 * graphControl1.NodeRadius));
            }
            for (int i = 1; i < graphControl1.Graph.Nodes.Count; i++)
            {
                Edge e = graphControl1.Graph.Edges.Add(graphControl1.Graph.Nodes[i - 1], graphControl1.Graph.Nodes[i]);
                e.Weight = r.Next(1, 25);
            }
            while (true)
            {
                int diameter = UnweightedDiameter();
                if (diameter <= numericUpDown1.Value)
                    break;
                int s = -1;
                int t = -1;

                while (true)
                {
                    if (s != t)
                    {
                        Node sn = graphControl1.Graph.Nodes[s];
                        Node tn = graphControl1.Graph.Nodes[t];
                        if (sn.OutEdges[tn] == null)
                        {
                            if (sn.OutEdges.Count <= 4 && tn.OutEdges.Count <= 4)
                            {
                                Edge e = graphControl1.Graph.Edges.Add(sn, tn);
                                e.Weight = r.Next(1, 25);
                                break;
                            }
                        }
                    }
                    s = r.Next(graphControl1.Graph.Nodes.Count);
                    t = r.Next(graphControl1.Graph.Nodes.Count);
                }
            }
            foreach (Node n in graphControl1.Graph.Nodes)
            {
                while (n.OutEdges.Count < 3)
                {
                    List<Node> fewEdges = new List<Node>();
                    foreach (Node n2 in graphControl1.Graph.Nodes)
                    {
                        if (n2.OutEdges.Count <= 4 && n2 != n && n.OutEdges[n2] == null)
                        {
                            fewEdges.Add(n2);
                        }
                    }
                    if (fewEdges.Count == 0)
                        break;
                    int x = r.Next(fewEdges.Count);
                    Node tn = fewEdges[x];
                    Edge e = graphControl1.Graph.Edges.Add(n, tn);
                    e.Weight = r.Next(1, 25);
                }
            }
            button3.Enabled = true;
            button4.Enabled = true;
        }

        private int UnweightedDiameter()
        {
            int diameter = 0;
            for (int i = 0; i < graphControl1.Graph.Nodes.Count; i++)
            {
                Node s = graphControl1.Graph.Nodes[i];
                for (int j = i + 1; j < graphControl1.Graph.Nodes.Count; j++)
                {
                    Node t = graphControl1.Graph.Nodes[j];
                    List<Node> path = GraphAlgorithms.GraphAlgorithms.Breitensuche(graphControl1.Graph, s, t);
                    if (path.Count - 1 > diameter)
                    {
                        diameter = path.Count - 1;
                    }
                }
            }
            return diameter;
        }

        List<Node>[] paths;

        private void graphControl1_NodeDoubleClicked(object sender, Node node)
        {
            if (graphControl1.Graph != null)
            {
                foreach (Edge e in graphControl1.Graph.Edges)
                    e.Color = Color.Black;
            }
            listBox1.Items.Clear();
            if (node == null)
            {
                paths = null;
                label3.Text = "Optimale Route von ... aus:";
                return;
            }
            paths = new List<Node>[graphControl1.Graph.Nodes.Count - 1];
            label3.Text = "Optimale Route von '" + node.Label + "' aus:";
            foreach (Node n in graphControl1.Graph.Nodes)
            {
                if (n != node)
                {
                    List<Node> l = GraphAlgorithms.GraphAlgorithms.Dijkstra(graphControl1.Graph, node, n);
                    float weight = 0;
                    for (int i = 1; i < l.Count; i++)
                    {
                        weight += l[i - 1].OutEdges[l[i]].Weight;
                    }
                    paths[listBox1.Items.Count] = l;
                    listBox1.Items.Add(n.Label + " über " + l[1].Label + " (" + weight + ")");
                }
            }
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs ea)
        {
            foreach (Edge e in graphControl1.Graph.Edges)
                e.Color = Color.Black;
            if (paths != null && listBox1.SelectedIndex >= 0)
            {
                List<Node> p = paths[listBox1.SelectedIndex];
                for (int i = 1; i < p.Count; i++)
                {
                    Node src = p[i - 1];
                    src.OutEdges[p[i]].Color = Color.Red;
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "Graph-Beschreibungen (*.xml)|*.xml";
            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                graphControl1.Graph = new Graph(ofd.FileName);
                textBox1.Text = string.Empty;
                foreach (Node n in graphControl1.Graph.Nodes)
                {
                    textBox1.Text += n.Label + "\r\n";
                    button3.Enabled = true;
                    button4.Enabled = true;
                }
                label3.Text = "Optimale Route von ... aus:";
                listBox1.Items.Clear();
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "Graph-Beschreibungen (*.xml)|*.xml";
            if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                if (graphControl1.Graph != null)
                {
                    foreach (Edge ed in graphControl1.Graph.Edges)
                        ed.Color = Color.Black;
                }
                graphControl1.Graph.SaveToXml(sfd.FileName);
                listBox1_SelectedIndexChanged(null, null);
            }
        }

        public double MeasureTextWidth(string text, OfficeOpenXml.Style.ExcelFont font)
        {
            if (string.IsNullOrEmpty(text)) return 0.0;
            var bitmap = new Bitmap(1, 1);
            var graphics = Graphics.FromImage(bitmap);

            var drawingFont = new Font(font.Name, font.Size);
            var size = graphics.MeasureString(text, drawingFont, 1000);

            //72 DPI and 96 points per inch.  Excel height in points with max of 409 per Excel requirements.
            return Math.Min(Convert.ToDouble(size.Width) * 72 / 96, 409);
        }

        private void button4_Click(object sender, EventArgs e)
        {
            if (graphControl1.Graph != null)
            {
                if (graphControl1.Graph.Nodes.Count > 14)
                {
                    MessageBox.Show("Warnung: Bei mehr als 14 Knoten kann es zu Darstellungsproblemen kommen.");
                }
                SaveFileDialog sfd = new SaveFileDialog();
                sfd.Filter = "Excel-Dateien (*.xlsx)|*.xlsx";
                if (sfd.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                    return;
                try
                {
                    FileInfo fi = new FileInfo(sfd.FileName);
                    fi.Delete();
                    double? headerHeight = null;
                    using (ExcelPackage excelFile = new ExcelPackage(fi))
                    {
                        ExcelStyleCollection<OfficeOpenXml.Style.XmlAccess.ExcelNamedStyleXml> oldStyles = excelFile.Workbook.Styles.NamedStyles;
                        OfficeOpenXml.Style.XmlAccess.ExcelNamedStyleXml headerStyle = excelFile.Workbook.Styles.CreateNamedStyle("Header", oldStyles[0].Style);
                        headerStyle.Style.TextRotation = 90;
                        headerStyle.Style.Font.Size = 11;
                        headerStyle.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
                        OfficeOpenXml.Style.XmlAccess.ExcelNamedStyleXml grayedStyle = excelFile.Workbook.Styles.CreateNamedStyle("Grayed", oldStyles[0].Style);
                        grayedStyle.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
                        grayedStyle.Style.Fill.BackgroundColor.SetColor(Color.FromArgb(170, 170, 170));
                        OfficeOpenXml.Style.XmlAccess.ExcelNamedStyleXml crossedStyle = excelFile.Workbook.Styles.CreateNamedStyle("Crossed", oldStyles[0].Style);
                        crossedStyle.Style.Border.DiagonalDown = true;
                        crossedStyle.Style.Border.DiagonalUp = true;
                        crossedStyle.Style.Border.Diagonal.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
                        double LINE_HEIGHT = 26;
                        double GAP_HEIGHT = 40;
                        double FACTOR = 0.037; // eine Einheit entspricht 0,035 cm
                        int nNumTablesPerPage;
                        for (int iN = 0; iN < graphControl1.Graph.Nodes.Count; iN++)
                        {
                            Node n = graphControl1.Graph.Nodes[iN];
                            ExcelWorksheet sheet = excelFile.Workbook.Worksheets.Add(n.Label);
                            sheet.HeaderFooter.OddHeader.CenteredText = n.Label;
                            sheet.Cells.Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center;
                            sheet.PrinterSettings.PaperSize = ePaperSize.A4;
                            if (!headerHeight.HasValue)
                            {
                                headerHeight = 0;
                                foreach (Node nn in graphControl1.Graph.Nodes)
                                {
                                    double h = MeasureTextWidth("über\r\n" + nn.Label, headerStyle.Style.Font);
                                    if (h > headerHeight) headerHeight = h;
                                }
                                headerHeight = Math.Ceiling(headerHeight.Value + 5);
                            }
                            string strNeighbors = "";
                            if (n.OutEdges.Count == 1)
                                strNeighbors = n.OutEdges[0].Target.Label;
                            else
                            {
                                for (int iE = 0; iE < n.OutEdges.Count; iE++)
                                {
                                    if (iE == n.OutEdges.Count - 1)
                                    {
                                        strNeighbors += " und ";
                                    }
                                    else if (iE > 0)
                                    {
                                        strNeighbors += ", ";
                                    }
                                    strNeighbors += n.OutEdges[iE].Target.Label;
                                }
                            }
                            string strIntro = string.Format("Die folgenden Schritte müssen in jedem Zeitschritt durchgeführt werden:\r\n" +
                                "1. Bestimmen Sie Ihren Distanzvektor. Er besteht aus dem kleinsten Wert jeder Zeile. Tragen Sie die Werte in die Spalte ganz rechts ein.\r\n" +
                                "2. Tragen Sie diese Werte auf jedes Nachrichtenblatt ein und geben Sie es jeweils an Ihre Nachbarn ({0}).\r\n" +
                                "3. Sie erhalten im Gegenzug Nachrichten von Ihren Nachbarn, z.B. von {1}. Sein/Ihr Abstand zu Ihnen ist {2}, tragen Sie also alle Werte, " +
                                "die Sie von ihm/ihr erhalten in die Spalte \"über {1}\" ein und addieren Sie jeweils {2}.", strNeighbors, n.OutEdges[0].Target.Label, n.OutEdges[0].Weight);
                            sheet.Cells[1, 1, 1, graphControl1.Graph.Nodes.Count + 3].Merge = true;
                            sheet.Cells[1, 1].Value = strIntro;
                            sheet.Cells[1, 1].Style.WrapText = true;
                            sheet.Row(1).Height = 3.8 / FACTOR;
                            sheet.Row(2).Height = 0.5 / FACTOR;

                            sheet.Cells[1, 1, 1, graphControl1.Graph.Nodes.Count + 3].Style.Border.BorderAround(OfficeOpenXml.Style.ExcelBorderStyle.Thin);

                            double tableHeight = (headerHeight.Value + LINE_HEIGHT * graphControl1.Graph.Nodes.Count) * FACTOR;

                            double gapHeightCM = GAP_HEIGHT * FACTOR;

                            double dNumberOfTablesPerPage = (29.7 - 1.7 - 2.5 + gapHeightCM) / (tableHeight + gapHeightCM);
                            while (dNumberOfTablesPerPage % 1 > 0.85)
                            {
                                if (GAP_HEIGHT > 30)
                                    GAP_HEIGHT--;
                                else
                                    LINE_HEIGHT--;
                                tableHeight = (headerHeight.Value + LINE_HEIGHT * graphControl1.Graph.Nodes.Count) * FACTOR;
                                dNumberOfTablesPerPage = (29.7 - 1.7 - 2.5 + gapHeightCM) / (tableHeight + gapHeightCM);
                            }
//                            nNumTablesPerPage = (int)dNumberOfTablesPerPage;

                            double lowerEnd = 3.8 + 0.5; 

                            for (int time = 0; time <= numericUpDown1.Value; time++)
                            {
                                int lineBase = 3 + time * (2 + graphControl1.Graph.Nodes.Count);
                                if (lowerEnd + tableHeight + FACTOR > 29.7 - 1.7 - 2.5)
                                {
                                    sheet.Row(lineBase - 1).Height = 1;
                                    sheet.Row(lineBase - 1).PageBreak = true;
                                    lowerEnd = tableHeight;
                                }
                                else
                                {
                                    if (time > 0)
                                        sheet.Row(lineBase - 1).Height = GAP_HEIGHT;
                                    lowerEnd += tableHeight + gapHeightCM;
                                }
                                sheet.Cells[lineBase, 1].Value = "Zeitschritt\r\n" + time;
                                sheet.Cells[lineBase, 1].Style.Font.Size = 13;
                                sheet.Cells[lineBase, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
                                for (int i = 0; i < graphControl1.Graph.Nodes.Count; i++)
                                {
                                    Node other = graphControl1.Graph.Nodes[i];
                                    sheet.Cells[lineBase + i + 1, 1].Value = "zu " + other.Label;
                                    sheet.Cells[lineBase + i + 1, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Left;
                                    sheet.Cells[lineBase, 2 + i].Value = "über\r\n" + other.Label;
                                    sheet.Row(lineBase + i + 1).Height = LINE_HEIGHT;
                                    Edge ed = n.OutEdges[other];
                                    if (ed == null)
                                        sheet.Cells[lineBase + 1, 2 + i, lineBase + graphControl1.Graph.Nodes.Count, 2 + i].StyleName = "Crossed";
                                    else
                                    {
                                        sheet.Cells[lineBase + 1 + i, 2 + i].Value = (int)ed.Weight;
                                        sheet.Cells[lineBase + 1 + i, 2 + i].Style.Font.Size = 15;
                                        sheet.Cells[lineBase + 1 + i, 2 + i].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
                                        if (time == 0)
                                        {
                                            sheet.Cells[lineBase + 1 + i, 2 + graphControl1.Graph.Nodes.Count].Value = (int)ed.Weight;
                                            sheet.Cells[lineBase + 1 + i, 2 + graphControl1.Graph.Nodes.Count].Style.Font.Size = 15;
                                            sheet.Cells[lineBase + 1 + i, 2 + graphControl1.Graph.Nodes.Count].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
                                        }
                                    }
                                }
                                sheet.Cells[iN + lineBase + 1, 2, iN + lineBase + 1, 2 + graphControl1.Graph.Nodes.Count].StyleName = "Grayed";
                                sheet.Cells[lineBase + 1, 2 + iN, lineBase + graphControl1.Graph.Nodes.Count, 2 + iN].StyleName = "Grayed";
                                sheet.Cells[lineBase, 2 + graphControl1.Graph.Nodes.Count].Value = "Distanz-\r\nvektor";
                                sheet.Cells[lineBase, 2, lineBase, graphControl1.Graph.Nodes.Count + 2].StyleName = "Header";
                                sheet.Row(lineBase).Height = headerHeight.Value;
                                ExcelRange all = sheet.Cells[lineBase, 1, lineBase + graphControl1.Graph.Nodes.Count, graphControl1.Graph.Nodes.Count + 2];
                                all.Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
                                all.Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
                                all.Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
                                all.Style.Border.Top.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
                                sheet.Cells[lineBase, graphControl1.Graph.Nodes.Count + 2, lineBase + graphControl1.Graph.Nodes.Count, graphControl1.Graph.Nodes.Count + 2].Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Double;

                            }
                            for (int i = 0; i <= graphControl1.Graph.Nodes.Count; i++)
                            {
                                sheet.Column(2 + i).Width = 5; // 0,98 cm => 1 entspricht 0,2 cm Breite
                            }
                            ExcelColumn col = sheet.Column(1);
                            col.AutoFit();
                            double maxFirstCol = 17.2 - (graphControl1.Graph.Nodes.Count + 1) * 0.98;
                            if (maxFirstCol * 5 < col.Width)
                                col.Width = maxFirstCol * 5;
                            sheet.Column(3 + graphControl1.Graph.Nodes.Count).Width = 5 * Math.Max(0, 17.2 - (col.Width / 5 + (graphControl1.Graph.Nodes.Count + 1) * 0.98));
                        }
                        ExcelWorksheet shMsgs = excelFile.Workbook.Worksheets.Add("Nachrichten");
                        shMsgs.Cells.Style.Font.Size = 13;
                        int row = 1;
                        shMsgs.Column(1).Width = 15;
                        for (int i = 1; i < numericUpDown1.Value; i++)
                            shMsgs.Column(i + 1).Width = 8;
                        shMsgs.Cells.Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center;
                        LINE_HEIGHT = 21;
                        GAP_HEIGHT = LINE_HEIGHT;

                        double HEADER_HEIGHT = 3 * 15 + 19;
                        double cardHeight = (HEADER_HEIGHT + LINE_HEIGHT * graphControl1.Graph.Nodes.Count) * FACTOR;

                        double gh = 2 * GAP_HEIGHT * FACTOR;

                        double dNumberOfCardsPerPage = (29.7 - 2.5 - 2.5 + gh) / (cardHeight + gh);
                        while (dNumberOfCardsPerPage % 1 > 0.85)
                        {
                            if (GAP_HEIGHT > 15)
                                GAP_HEIGHT--;
                            else
                                LINE_HEIGHT--;
                            cardHeight = (headerHeight.Value + LINE_HEIGHT * graphControl1.Graph.Nodes.Count) * FACTOR;
                            dNumberOfCardsPerPage = (29.7 - 2.5 - 2.5 + gh) / (cardHeight + gh);
                        }
                        nNumTablesPerPage = (int)dNumberOfCardsPerPage;
                        int countTables = 0;
                        for (int i = 0; i < graphControl1.Graph.Nodes.Count; i++)
                        {
                            Node src = graphControl1.Graph.Nodes[i];
                            for (int j = 0; j < src.OutEdges.Count; j++)
                            {
                                countTables++;
                                int firstRow = row;
                                Node trg = src.OutEdges[j].Target;
                                shMsgs.Cells[row, 1].Value = "Von: " + src.Label;
                                shMsgs.Cells[row, 1, row, 2].Merge = true;
                                shMsgs.Cells[row, 3].Value = "An: " + trg.Label;
                                shMsgs.Cells[row, 3, row, (int)numericUpDown1.Value + 1].Merge = true;
                                row++;
                                shMsgs.Cells[row, 1].Value = "Mein neuer Distanzvektor";
                                shMsgs.Cells[row, 1].Style.Font.Bold = true;
                                shMsgs.Cells[row, 1].Style.Font.Size += 2;
                                shMsgs.Row(row).Height = 19;
                                shMsgs.Cells[row, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
                                shMsgs.Cells[row, 1, row, (int)numericUpDown1.Value + 1].Merge = true;
                                row++;
                                shMsgs.Cells[row, 1].Value = "Distanz\r\nzu:";
                                shMsgs.Cells[row, 1, row + 1, 1].Merge = true;
                                shMsgs.Cells[row, 2].Value = "nach Zeitschritt";
                                shMsgs.Cells[row, 2].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
                                shMsgs.Cells[row, 2, row, (int)numericUpDown1.Value + 1].Merge = true;
                                row++;
                                for (int k = 0; k < numericUpDown1.Value; k++)
                                {
                                    shMsgs.Cells[row, 2 + k].Value = k;
                                    shMsgs.Cells[row, 2 + k].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
                                }
                                row++;
                                foreach (Node n in graphControl1.Graph.Nodes)
                                {
                                    shMsgs.Cells[row, 1].Value = n.Label;
                                    shMsgs.Row(row).Height = LINE_HEIGHT;
                                    if (n == src || n == trg)
                                    {
                                        for (int k = 0; k < numericUpDown1.Value; k++)
                                        {
                                            shMsgs.Cells[row, 2 + k].Style.Border.Diagonal.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
                                            shMsgs.Cells[row, 2 + k].Style.Border.DiagonalDown = true;
                                            shMsgs.Cells[row, 2 + k].Style.Border.DiagonalUp = true;
                                        }
                                    }
                                    row++;
                                }
                                ExcelRange range = shMsgs.Cells[firstRow, 1, row - 1, (int)numericUpDown1.Value + 1];
                                range.Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
                                range.Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
                                range.Style.Border.Top.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
                                range.Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
                                shMsgs.Cells[firstRow + 2, 2].Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.None;
                                shMsgs.Cells[firstRow + 3, 2, firstRow + 3, (int)numericUpDown1.Value + 1].Style.Border.Top.Style = OfficeOpenXml.Style.ExcelBorderStyle.None;
                                if (countTables == nNumTablesPerPage)
                                {
                                    shMsgs.Row(row).Height = 1;
                                    shMsgs.Row(row).PageBreak = true;
                                    countTables = 0;
                                }
                                else
                                {
                                    shMsgs.Row(row).Height = GAP_HEIGHT;
                                    ExcelRange er = shMsgs.Cells[row, 1];
                                    er.Value = "(hier auseinanderschneiden)";
                                    er.Style.Font.Size = 8;
                                    er.Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Bottom;
                                    er.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
                                    shMsgs.Cells[row, 1, row, (int)numericUpDown1.Value + 2].Merge = true;
                                    shMsgs.Cells[row, 1, row, (int)numericUpDown1.Value + 2].Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Dashed;
                                    row++;
                                    er = shMsgs.Cells[row, 1];
                                    er.Value = "(hier auseinanderschneiden)";
                                    er.Style.Font.Size = 8;
                                    er.Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Top;
                                    er.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
                                    shMsgs.Cells[row, 1, row, (int)numericUpDown1.Value + 2].Merge = true;
                                    shMsgs.Row(row).Height = GAP_HEIGHT;
                                }
                                row++;
                            }
                        }
                        shMsgs.Column((int)numericUpDown1.Value + 2).Width = 5 * Math.Max(0, 17.2 - (3 + 1.8*(double)numericUpDown1.Value));
                         excelFile.Save();
                    }
                }
                catch (Exception x)
                {
                    MessageBox.Show(x.Message);
                }
            }
        }
    }
}
