using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System.IO;

namespace OpenXMLSample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

    
        private void btnSample1_Click(object sender, EventArgs e)
        {
            // 新しいExcelドキュメントを作成
            SpreadsheetDocument document = SpreadsheetDocument.Create("sample1.xlsx", SpreadsheetDocumentType.Workbook, true);

            // ドキュメントのワークブックパートに、ワークブックを設定
            WorkbookPart wbpart = document.AddWorkbookPart();
            wbpart.Workbook = new Workbook();

            // ワークブックパートに、ワークシートパートを設定
            WorksheetPart wspart = wbpart.AddNewPart<WorksheetPart>();
            SheetData sheetData = new SheetData();
            wspart.Worksheet = new Worksheet(sheetData);

            // ワークブックにシートを設定
            Sheets sheets = wbpart.Workbook.AppendChild<Sheets>(new Sheets());

            // シートを1つ追加
            Sheet sheet = new Sheet() { Id = wbpart.GetIdOfPart(wspart), SheetId = 1, Name = "Sheet1" };
            sheets.Append(sheet);

            // SheetDataにデータを設定していく

            // Rowオブジェクトを作成し、そこにCellデータを追加
            Row row = new Row();
            
            Cell cell = new Cell();
            cell.DataType = CellValues.String;
            cell.CellReference = "A1";
            cell.CellValue = new CellValue("テスト出力");

            row.Append(cell);

            // 最後にRowをSheetDataに追加
            sheetData.Append(row);



            // ファイルを保存
            document.Close();

        }



        private static Stylesheet CreateStylesheet()
        {

            Stylesheet ss = new Stylesheet();

            Fonts fts = new Fonts();

            // ID:0のフォント
            DocumentFormat.OpenXml.Spreadsheet.Font ft = new DocumentFormat.OpenXml.Spreadsheet.Font();
            FontName ftn = new FontName();
            ftn.Val = StringValue.FromString("Arial");
            FontSize ftsz = new FontSize();
            ftsz.Val = DoubleValue.FromDouble(11);
            ft.FontName = ftn;
            ft.FontSize = ftsz;
            fts.Append(ft);

            // ID:1のフォント
            ft = new DocumentFormat.OpenXml.Spreadsheet.Font();
            ftn = new FontName();
            ftn.Val = StringValue.FromString("Arial");
            ftsz = new FontSize();
            ftsz.Val = DoubleValue.FromDouble(18);
            ft.FontName = ftn;
            ft.FontSize = ftsz;

            // Boldの指定を追加
            ft.Append(new Bold());
            fts.Append(ft);

            fts.Count = UInt32Value.FromUInt32((uint)fts.ChildElements.Count);

            // 塗りつぶしパターン
            Fills fills = new Fills();
            Fill fill = new Fill();
            // ID:0の塗りつぶしパターン
            fills.Append(fill);

            PatternFill patternFill;
            // ID:1の塗りつぶしパターン
            fill = new Fill();
            patternFill = new PatternFill();
            patternFill.PatternType = PatternValues.Gray125;
            fill.PatternFill = patternFill;
            fills.Append(fill);

            // ID:2の塗りつぶしパターン
            fill = new Fill();
            patternFill = new PatternFill();
            patternFill.PatternType = PatternValues.DarkGray;
            patternFill.ForegroundColor = new ForegroundColor();
            patternFill.ForegroundColor.Rgb = HexBinaryValue.FromString("0000FF");
            
            patternFill.BackgroundColor = new BackgroundColor();
            patternFill.BackgroundColor.Rgb = patternFill.ForegroundColor.Rgb;
            fill.PatternFill = patternFill;
            fills.Append(fill);

            fills.Count = UInt32Value.FromUInt32((uint)fills.ChildElements.Count);

            // 罫線パターン
            Borders borders = new Borders();
            Border border = new Border();
            // ID:0の罫線パターン
            borders.Append(border);

            // ID:1の罫線パターン
            border = new Border();
            // セルの左側の罫線
            border.LeftBorder = new LeftBorder();
            border.LeftBorder.Style = BorderStyleValues.Thin;
            // セルの右側の罫線
            border.RightBorder = new RightBorder();
            border.RightBorder.Style = BorderStyleValues.Thin;
            // セルの上側の罫線
            border.TopBorder = new TopBorder();
            border.TopBorder.Style = BorderStyleValues.Thin;
            // セルの下側の罫線
            border.BottomBorder = new BottomBorder();
            border.BottomBorder.Style = BorderStyleValues.Thin;

            border.DiagonalBorder = new DiagonalBorder();
            borders.Append(border);


            borders.Count = UInt32Value.FromUInt32((uint)borders.ChildElements.Count);


            CellStyleFormats csfs = new CellStyleFormats();
            CellFormat cf = new CellFormat();
            cf.FontId = 0;
            cf.FillId = 0;
            cf.BorderId = 0;
            csfs.Append(cf);
            csfs.Count = UInt32Value.FromUInt32((uint)csfs.ChildElements.Count);

            // 書式設定
            NumberingFormats nfs = new NumberingFormats();
            NumberingFormat nf = new NumberingFormat();
            nf.NumberFormatId = UInt32Value.FromUInt32(9999);
            nf.FormatCode = StringValue.FromString("#,##0.0000");
            nfs.Append(nf);


            CellFormats cfs = new CellFormats();

            // index 0
            cf = new CellFormat();
            cf.NumberFormatId = 0;
            cf.FontId = 0;
            cf.FillId = 0;
            cf.BorderId = 0;
            cf.FormatId = 0;
            cfs.Append(cf);

            // index 1
            cf = new CellFormat();
            // 使用するフォントのIDを指定
            cf.FontId = 1;
            cf.FillId = 0;
            cf.BorderId = 0;
            cf.FormatId = 0;
            cf.ApplyNumberFormat = BooleanValue.FromBoolean(true);
            cfs.Append(cf);

            // index 2
            cf = new CellFormat();
            cf.FontId = 0;
            cf.FillId = 0;
            cf.BorderId = 0;
            cf.FormatId = 0;
            cf.ApplyNumberFormat = BooleanValue.FromBoolean(true);
            // 使用する書式のIDを指定
            cf.NumberFormatId = 9999;
            cfs.Append(cf);

            // index 3
            cf = new CellFormat();
            cf.FontId = 0;
            cf.FillId = 0;
            // 使用する罫線のIDを指定
            cf.BorderId = 1;
            cf.FormatId = 0;
            cfs.Append(cf);
            
            // index 4
            cf = new CellFormat();
            cf.FontId = 0;
            // 使用する塗りつぶしのIDを指定
            cf.FillId = 1;
            cf.BorderId = 0;
            cf.FormatId = 0;
            cfs.Append(cf);
            
            // index 5
            cf = new CellFormat();
            cf.FontId = 0;
            // 使用する塗りつぶしのIDを指定
            cf.FillId = 2;
            cf.BorderId = 0;
            cf.FormatId = 0;
            cfs.Append(cf);

            nfs.Count = UInt32Value.FromUInt32((uint)nfs.ChildElements.Count);
            cfs.Count = UInt32Value.FromUInt32((uint)cfs.ChildElements.Count);
            
            ss.Append(fts);
            ss.Append(fills);
            ss.Append(borders);
            ss.Append(csfs);
            ss.Append(cfs);
            ss.NumberingFormats = nfs;

            return ss;
        }

        private void btnSample2_Click(object sender, EventArgs e)
        {
            // 新しいExcelドキュメントを作成
            SpreadsheetDocument document = SpreadsheetDocument.Create("sample2.xlsx", SpreadsheetDocumentType.Workbook, true);

            // ドキュメントのワークブックパートに、ワークブックを設定
            WorkbookPart wbpart = document.AddWorkbookPart();
            wbpart.Workbook = new Workbook();

            // ワークブックパートに、ワークシートパートを設定
            WorksheetPart wspart = wbpart.AddNewPart<WorksheetPart>();
            SheetData sheetData = new SheetData();
            wspart.Worksheet = new Worksheet(sheetData);

            // スタイル設定
            WorkbookStylesPart stylesPart = wbpart.AddNewPart<WorkbookStylesPart>();
            stylesPart.Stylesheet = CreateStylesheet();

            stylesPart.Stylesheet.Save();


            // ワークブックにシートを設定
            Sheets sheets = wbpart.Workbook.AppendChild<Sheets>(new Sheets());

            // シートを1つ追加
            Sheet sheet = new Sheet() { Id = wbpart.GetIdOfPart(wspart), SheetId = 1, Name = "Sheet1" };
            sheets.Append(sheet);

            // SheetDataにデータを設定していく

            // Rowオブジェクトを作成し、そこにCellデータを追加
            Row row = new Row();

            Cell cell = new Cell();
            cell.DataType = CellValues.String;
            cell.CellReference = "A1";
            cell.CellValue = new CellValue("テスト出力");

            // ここで、このセルに適用するスタイルを指定
            cell.StyleIndex = 1;

            row.Append(cell);

            // 最後にRowをSheetDataに追加
            sheetData.Append(row);

            // ファイルを保存
            document.Close();
        }

        private void btnSample3_Click(object sender, EventArgs e)
        {
            // 新しいExcelドキュメントを作成
            SpreadsheetDocument document = SpreadsheetDocument.Create("sample3.xlsx", SpreadsheetDocumentType.Workbook, true);

            // ドキュメントのワークブックパートに、ワークブックを設定
            WorkbookPart wbpart = document.AddWorkbookPart();
            wbpart.Workbook = new Workbook();

            // ワークブックパートに、ワークシートパートを設定
            WorksheetPart wspart = wbpart.AddNewPart<WorksheetPart>();
            SheetData sheetData = new SheetData();
            wspart.Worksheet = new Worksheet(sheetData);

            // スタイル設定
            WorkbookStylesPart stylesPart = wbpart.AddNewPart<WorkbookStylesPart>();
            stylesPart.Stylesheet = CreateStylesheet();

            stylesPart.Stylesheet.Save();


            // ワークブックにシートを設定
            Sheets sheets = wbpart.Workbook.AppendChild<Sheets>(new Sheets());

            // シートを1つ追加
            Sheet sheet = new Sheet() { Id = wbpart.GetIdOfPart(wspart), SheetId = 1, Name = "Sheet1" };
            sheets.Append(sheet);

            // SheetDataにデータを設定していく

            // Rowオブジェクトを作成し、そこにCellデータを追加
            Row row = new Row();

            Cell cell = new Cell();
            cell.DataType = CellValues.Number;
            cell.CellReference = "A1";
            cell.CellValue = new CellValue("12345.1230");

            // ここで、このセルに適用するスタイルを指定
            cell.StyleIndex = 2;

            row.Append(cell);

            // 最後にRowをSheetDataに追加
            sheetData.Append(row);

            // ファイルを保存
            document.Close();
        }

        private void btnSample4_Click(object sender, EventArgs e)
        {
            // 新しいExcelドキュメントを作成
            SpreadsheetDocument document = SpreadsheetDocument.Create("sample4.xlsx", SpreadsheetDocumentType.Workbook, true);

            // ドキュメントのワークブックパートに、ワークブックを設定
            WorkbookPart wbpart = document.AddWorkbookPart();
            wbpart.Workbook = new Workbook();

            // ワークブックパートに、ワークシートパートを設定
            WorksheetPart wspart = wbpart.AddNewPart<WorksheetPart>();
            SheetData sheetData = new SheetData();
            wspart.Worksheet = new Worksheet(sheetData);

            // スタイル設定
            WorkbookStylesPart stylesPart = wbpart.AddNewPart<WorkbookStylesPart>();
            stylesPart.Stylesheet = CreateStylesheet();

            stylesPart.Stylesheet.Save();


            // ワークブックにシートを設定
            Sheets sheets = wbpart.Workbook.AppendChild<Sheets>(new Sheets());

            // シートを1つ追加
            Sheet sheet = new Sheet() { Id = wbpart.GetIdOfPart(wspart), SheetId = 1, Name = "Sheet1" };
            sheets.Append(sheet);

            Cell cell = InsertCellInWorksheet("B", 3, wspart);
            cell.DataType = CellValues.String;
            cell.CellValue = new CellValue("テスト１");
            cell.StyleIndex = 3;


            cell = InsertCellInWorksheet("C", 3, wspart);
            cell.DataType = CellValues.String;
            cell.CellValue = new CellValue("テスト２");
            cell.StyleIndex = 3;

            // ファイルを保存
            document.Close();


        }

        /// <summary>
        /// 指定した行番号およびカラム名でセルを作成
        /// セルの作成は左上から順番に作成する必要がある
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="rowIndex"></param>
        /// <param name="worksheetPart"></param>
        /// <returns></returns>
        private Cell InsertCellInWorksheet(string columnName, uint rowIndex, WorksheetPart worksheetPart)
        {
            Worksheet worksheet = worksheetPart.Worksheet;
            SheetData sheetData = worksheet.GetFirstChild<SheetData>();
            string cellReference = columnName + rowIndex;

            // 行番号を特定
            Row row;
            if (sheetData.Elements<Row>().Where(r => r.RowIndex == rowIndex).Count() != 0)
            {
                row = sheetData.Elements<Row>().Where(r => r.RowIndex == rowIndex).First();
            }
            else
            {
                row = new Row() { RowIndex = rowIndex };
                sheetData.Append(row);
            }

            // カラム番号を特定
            if (row.Elements<Cell>().Where(c => c.CellReference.Value == columnName + rowIndex).Count() > 0)
            {
                return row.Elements<Cell>().Where(c => c.CellReference.Value == cellReference).First();
            }
            else
            {
                Cell refCell = null;
                foreach (Cell cell in row.Elements<Cell>())
                {
                    if (cell.CellReference.Value.Length == cellReference.Length)
            {
                        if (string.Compare(cell.CellReference.Value, cellReference, true) > 0)
                        {
                            refCell = cell;
                            break;
                        }
                    }
                }

                Cell newCell = new Cell() { CellReference = cellReference };
                row.InsertBefore(newCell, refCell);

                worksheet.Save();
                return newCell;
            }
        }

        private void btnSample5_Click(object sender, EventArgs e)
        {
            // 新しいExcelドキュメントを作成
            SpreadsheetDocument document = SpreadsheetDocument.Create("sample5.xlsx", SpreadsheetDocumentType.Workbook, true);

            // ドキュメントのワークブックパートに、ワークブックを設定
            WorkbookPart wbpart = document.AddWorkbookPart();
            wbpart.Workbook = new Workbook();

            // ワークブックパートに、ワークシートパートを設定
            WorksheetPart wspart = wbpart.AddNewPart<WorksheetPart>();
            SheetData sheetData = new SheetData();
            wspart.Worksheet = new Worksheet(sheetData);

            // スタイル設定
            WorkbookStylesPart stylesPart = wbpart.AddNewPart<WorkbookStylesPart>();
            stylesPart.Stylesheet = CreateStylesheet();

            stylesPart.Stylesheet.Save();


            // ワークブックにシートを設定
            Sheets sheets = wbpart.Workbook.AppendChild<Sheets>(new Sheets());

            // シートを1つ追加
            Sheet sheet = new Sheet() { Id = wbpart.GetIdOfPart(wspart), SheetId = 1, Name = "Sheet1" };
            sheets.Append(sheet);

            Cell cell = InsertCellInWorksheet("B", 2, wspart);
            cell.DataType = CellValues.String;
            cell.CellValue = new CellValue("テスト１");
            cell.StyleIndex = 4;


            cell = InsertCellInWorksheet("C", 3, wspart);
            cell.DataType = CellValues.String;
            cell.CellValue = new CellValue("テスト２");
            cell.StyleIndex = 5;

            // ファイルを保存
            document.Close();
        }
    }
}
