Strict Open XML 形式のブックをコンポーネントで扱う

Open XML SDL 2.5 CTP 版と ExcelCreator を使用し、プログラム中から Strict Open XML 形式の Excel ブック (.xlsx) を扱う方法を紹介します。


◆検証環境
OS Windows 8(x64)
開発環境 Visual Studio 2012
CPU Intel(R) Core(TM)2 Duo E8400 @ 3.00GHz
メモリ 4GB
その他 SSD 搭載


◆Open XML SDK 2.5 を使用して Strict Open XML 形式を扱う

Open XML SDK 2.5 の CTP 版では、Strict Open XML 形式の読み込みがサポートされます。Visual Studio 2012 でコンソールアプリケーション「OXML25ConsoleApplication」を新規作成し、Open XML SDK 2.5 のアセンブリへの参照を追加してコードを述していきます。

ブックをオープンしてセルに値を設定するコード(Open XML SDK 2.5)

using System;
using System.Diagnostics;
using System.Linq;
using System.Drawing;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

namespace OXML25ConsoleApplication
{
    /// <summary>
    /// Program クラス
    /// </summary>
    class Program
    {
        /// <summary>
        /// private メンバ
        /// </summary>
        private static SpreadsheetDocument spreadsheetDocument = null;
        private static WorkbookPart workbookPart = null;
        private static WorksheetPart worksheetPart = null;
        private static SharedStringTablePart sharedStringPart = null;
        /// <summary>
        /// Main
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            TimeSpan ts = new TimeSpan();
            sw.Start();
            Console.WriteLine("Open XML SDK 2.5 による Strict Open XML 形式のブックのオープン。");

            // SpreadsheetDocument をオープンします。
            spreadsheetDocument = SpreadsheetDocument.Open(@"明細s.xlsx", true);

            // WorkbookPart を取得します。
            workbookPart = spreadsheetDocument.WorkbookPart;

            // WorksheetPart を取得します。
            IEnumerable<Sheet> sheets = spreadsheetDocument.WorkbookPart.Workbook.Descendants<Sheet>().Where
                (s => s.Name == "Sheet1");
            worksheetPart = (WorksheetPart)spreadsheetDocument.WorkbookPart.GetPartById(sheets.First().Id);

            // SharedStringTablePart を作成します。
            OpensharedStringPart();

            // データの設定
            SetData();

            // ワークブックを保存します。
            workbookPart.Workbook.Save();

            // ドキュメントをクローズします。
            spreadsheetDocument.Close();

            ts = sw.Elapsed;
            Console.WriteLine("Open XML SDK 2.5 処理時間:{0}", ts.ToString());
            Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
            currentProcess.Refresh();
            Console.WriteLine("プロセス名   :" + currentProcess.ProcessName + "\n" +
                "物理メモリ使用量:" + (currentProcess.WorkingSet64 / 1024) + " KB\n" +
                "仮想メモリ使用量:" + (currentProcess.VirtualMemorySize64 / 1024) + " KB");

        }
        /// <summary>
        /// データを設定します。
        /// </summary>
        /// <param name="sheet"></param>
        private static void SetData()
        {
            // データ
            SetValue("B", 3, "ExcelCreator 2012");
            SetValue("C", 3, 1);
            SetValue("D", 3, 63000);
            SetValue("E", 3, 63000);
            SetValue("B", 4, "VB-Report 7");
            SetValue("C", 4, 1);
            SetValue("D", 4, 81900);
            SetValue("E", 4, 81900);
            SetValue("B", 5, "Open XML SDK 2.5 CTP 版によるデータの書き込み。(Strict Open XML 形式)");
        }
        /// <summary>
        /// SharedStringTable を開く
        /// </summary>
        private static void OpensharedStringPart()
        {
            if (spreadsheetDocument == null) return;
            if (spreadsheetDocument.WorkbookPart.GetPartsOfType<SharedStringTablePart>().Count() > 0)
                sharedStringPart = spreadsheetDocument.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First();
            else
                sharedStringPart = spreadsheetDocument.WorkbookPart.AddNewPart<SharedStringTablePart>();
        }
        /// <summary>
        /// SharedStringTable への値の設定
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        private static int InsertSharedStringItem(string text)
        {
            if (sharedStringPart == null) return -1;
            // 共有文字列テーブルのデータがない場合新規で作成する。
            if (sharedStringPart.SharedStringTable == null)
                sharedStringPart.SharedStringTable = new SharedStringTable();
            int index = 0;
            foreach (SharedStringItem item in sharedStringPart.SharedStringTable.Elements<SharedStringItem>())
            {
                if (item.InnerText == text)
                    return index;
                index++;
            }
            // 共有文字列に文字を設定
            sharedStringPart.SharedStringTable.AppendChild(new SharedStringItem(new DocumentFormat.OpenXml.Spreadsheet.Text(text)));
            return index;
        }
        /// <summary>
        /// 値の設定
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="rowIndex"></param>
        /// <param name="value"></param>
        private static void SetValue(string columnName, int rowIndex, object value)
        {
            Type type = value.GetType();

            string valueString = "";
            if (value != null)
                valueString = value.ToString();
            Cell cell = InsertCellInWorksheet(columnName, rowIndex, -1);
            if (type == typeof(string))
            {
                // Insert the result into the SharedStringTablePart.
                int index = InsertSharedStringItem(valueString);

                cell.CellValue = new CellValue(index.ToString());
                cell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
            }
            else
            {
                cell.CellValue = new CellValue(valueString);
                cell.DataType = new EnumValue<CellValues>(CellValues.Number);
            }
            return;
        }
        /// <summary>
        /// セル情報の検索と取得(存在しない場合は新規追加)
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="rowIndex"></param>
        /// <param name="styleIndex"></param>
        /// <returns></returns>
        private static Cell InsertCellInWorksheet(string columnName, int rowIndex, int styleIndex)
        {
            if (worksheetPart == null) return null;
            Worksheet worksheet = worksheetPart.Worksheet;
            SheetData sheetData = worksheet.GetFirstChild<SheetData>();
            string cellReference = columnName + rowIndex.ToString();

            // 列情報があるかを確認し、無い場合は新規で作成する。
            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 refRow = null;
                foreach (Row r in sheetData.Elements<Row>())
                {
                    if (r.RowIndex > rowIndex)
                    {
                        refRow = r;
                        break;
                    }
                }
                row = new Row() { RowIndex = (uint)rowIndex };
                sheetData.InsertBefore(row, refRow);
            }

            // 列番号から、セルの存在を確認する。
            if (row.Elements<Cell>().Where(c => c.CellReference.Value == columnName + rowIndex.ToString()).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 (string.Compare(cell.CellReference, cellReference) > 0)
                    {
                        refCell = cell;
                        break;
                    }
                }
                Cell newCell = new Cell() { CellReference = cellReference };
                if (styleIndex >= 0) newCell.StyleIndex = new UInt32Value((uint)styleIndex);
                row.InsertBefore(newCell, refCell);
                return newCell;
            }
        }
    }
}

Open XML SDK 2.5 の CTP 版の詳細は下記のサイトで紹介されています。

Open XML SDK 2.5 CTP for Office の新機能

Open XML SDK 2.5 の CTP 版では、読み込みはサポートされていますが、ブックを保存する場合は従来の Open XML 移行型 (Transitional) 形式のブックとして保存されます。そのため、新規に Strict Open XML 形式でブックを作成することはできないようです。実際に作成されたファイルの内容を見てみると、タグは Strict 形式のもので出力されていますが、各パーツの「xmlns」が従来のネームスペースのままで作成されています。

xl/workbook.xml の内容

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<x:workbook 
  xmlns:x15ac="http://schemas.microsoft.com/office/spreadsheetml/2010/11/ac" 
  xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" 
  xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" 
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main" 
  conformance="strict" 
  mc:Ignorable="x15" 
  xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<x:fileVersion appName="xl" lastEdited="6" lowestEdited="6" rupBuild="14420" />
<x:workbookPr dateCompatibility="0" defaultThemeVersion="153222" />
<mc:AlternateContent xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<mc:Choice Requires="x15">
<x15ac:absPath xmlns:x15ac="http://schemas.microsoft.com/office/spreadsheetml/2010/11/ac" url="D:\OpenBook\Release\" />
</mc:Choice>
</mc:AlternateContent>
<x:bookViews>
<x:workbookView xWindow="0" yWindow="0" windowWidth="14880" windowHeight="8055" />
</x:bookViews>
<x:sheets>
<x:sheet name="Sheet1" sheetId="1" r:id="rId1" />
</x:sheets>
<x:calcPr calcId="152511" />
<x:extLst>
<x:ext xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main" uri="{79F54976-1DA5-4618-B147-4CDE4B953A38}">
<x14:workbookPr />
</x:ext>
<x:ext xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main" uri="{140A7094-0E35-4892-8432-C4D2E57EDEB5}">
<x15:workbookPr chartTrackingRefBase="1" />
</x:ext>
</x:extLst>
</x:workbook>

尚、Open XML SDK 2.5 で作成したブックを Excel 2013 で開き、名前を付けて保存を選択すると、ファイルの種類にはデフォルトで「Strict Open XML スプレッドシート (*xlsx)」が選択されます。



◆ExcelCreator を使用して Strict Open XML 形式を扱う

ExcelCreator 8.0 for .NET では、2013/2/7 公開のアップデート版 (Ver8.0.5270.1707) から Strict Open XML 形式のブックがサポートされます。Visual Studio 2012 でコンソールアプリケーション「EC8ConsoleApplication」を新規作成し、ExcelCreator の各アセンブリへの参照および System.Drawing への参照を追加してコードを述していきます。

Strict Open XML 形式のブックを新規に作成するコード(ExcelCreator 8.0 for .NET)

using System;
using System.Diagnostics;
using AdvanceSoftware.ExcelCreator;
using AdvanceSoftware.ExcelCreator.Xlsx;
using System.Drawing;

namespace EC8ConsoleApplication
{
    /// <summary>
    /// Program クラス
    /// </summary>
    class Program
    {
        /// <summary>
        /// Main
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            TimeSpan ts = new TimeSpan();
            sw.Start();
            Console.WriteLine("ExcelCreator 8.0 for .NET による Strict Open XML 形式の新規作成。");

            var xlsxCreator = new XlsxCreator();
            // ブックの新規作成 - Strict Open XML 形式
            xlsxCreator.CreateBook("EC8Create.xlsx", 1, xlsxVersion.ver2013S);
            // シート名の設定
            xlsxCreator.SheetName = "明細";
            // レイアウトの設定
            SetLayout(xlsxCreator);
            // データの設定
            SetData(xlsxCreator);
            // ブックのクローズ
            xlsxCreator.CloseBook(true);

            ts = sw.Elapsed;
            Console.WriteLine("ExcelCreator 8.0 for .NET 処理時間:{0}", ts.ToString());
            Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
            currentProcess.Refresh();
            Console.WriteLine("プロセス名   :" + currentProcess.ProcessName + "\n" +
                "物理メモリ使用量:" + (currentProcess.WorkingSet64 / 1024) + " KB\n" +
                "仮想メモリ使用量:" + (currentProcess.VirtualMemorySize64 / 1024) + " KB");

        }
        /// <summary>
        /// レイアウトを設定します。
        /// </summary>
        /// <param name="xlsxCreator"></param>
        private static void SetLayout(XlsxCreator xlsxCreator)
        {
            if (xlsxCreator == null) return;
            // 罫線
            xlsxCreator.Cell("B2:E4").Attr.Box(BoxType.Ltc, BorderStyle.Medium, xlColor.Blue);
            // 背景色
            xlsxCreator.Cell("B2:E2").Attr.BackColor = Color.Blue;
            // タイトル行
            xlsxCreator.Cell("B2:E2").Attr.FontColor = Color.White;
            xlsxCreator.Cell("B2").Value = "商品名";
            xlsxCreator.Cell("C2").Value = "数量";
            xlsxCreator.Cell("D2").Value = "単価";
            xlsxCreator.Cell("E2").Value = "金額";
        }
        /// <summary>
        /// データを設定します。
        /// </summary>
        /// <param name="xlsxCreator"></param>
        private static void SetData(XlsxCreator xlsxCreator)
        {
            if (xlsxCreator == null) return;
            // データ
            xlsxCreator.Cell("B3").Value = "ExcelCreator 2012";
            xlsxCreator.Cell("C3").Value = 1;
            xlsxCreator.Cell("D3").Value = 63000;
            xlsxCreator.Cell("E3").Value = 63000;
            xlsxCreator.Cell("B4").Value = "VB-Report 7";
            xlsxCreator.Cell("C4").Value = 1;
            xlsxCreator.Cell("D4").Value = 81900;
            xlsxCreator.Cell("E4").Value = 81900;
        }
    }
}

ExcelCreator を使用して Strict Open XML 形式のブックを新規に作成するには、CreateBook メソッドのバージョンを指定する引数に「ver2013S」を指定します。作成されたブックの拡張子を「.zip」に変更して内容を確認すると Strict Open XML 形式で作成されていることが分かります。尚、バージョン指定時に「ver2013」を指定すると、Excel 2013 の従来の Open XML 移行型 (Transitional) 形式で作成されます。

xl/workbook.xml の内容

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<workbook 
  xmlns="http://purl.oclc.org/ooxml/spreadsheetml/main" 
  xmlns:r="http://purl.oclc.org/ooxml/officeDocument/relationships" 
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
  mc:Ignorable="x15" 
  xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main" 
  conformance="strict">
<fileVersion appName="xl" lastEdited="6" lowestEdited="6" rupBuild="14420" />
<workbookPr dateCompatibility="0" defaultThemeVersion="153222" />
<mc:AlternateContent xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<mc:Choice Requires="x15">
<x15ac:absPath url="D:\OpenBook\" xmlns:x15ac="http://schemas.microsoft.com/office/spreadsheetml/2010/11/ac" />
</mc:Choice>
</mc:AlternateContent>
<bookViews>
<workbookView xWindow="0" yWindow="0" windowWidth="15780" windowHeight="7710" />
</bookViews>
<sheets>
<sheet name="明細" sheetId="1" r:id="rId3" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" />
</sheets>
<calcPr calcId="152511" />
<extLst>
<ext uri="{79F54976-1DA5-4618-B147-4CDE4B953A38}" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main">
<x14:workbookPr />
</ext>
<ext uri="{140A7094-0E35-4892-8432-C4D2E57EDEB5}" xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main">
<x15:workbookPr chartTrackingRefBase="1" />
</ext>
</extLst>
</workbook>


次に既存の Strict Open XML 形式のブックをオープンしてセルにデータを書き込み別のファイルとして保存を行います。

ブックをオープンしてセルに値を設定するコード(ExcelCreator 8.0 for .NET)

using System;
using System.Diagnostics;
using AdvanceSoftware.ExcelCreator;
using AdvanceSoftware.ExcelCreator.Xlsx;
using System.Drawing;

namespace EC8ConsoleApplication
{
    /// <summary>
    /// Program クラス
    /// </summary>
    class Program
    {
        /// <summary>
        /// Main
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            TimeSpan ts = new TimeSpan();
            sw.Start();
            Console.WriteLine("ExcelCreator 8.0 for .NET による Strict Open XML 形式のブックのオープン。");

            var xlsxCreator = new XlsxCreator();
            // ブックのオープン
            xlsxCreator.OpenBook("EC8Open.xlsx", "明細s.xlsx");
            // データの設定
            SetData(xlsxCreator);
            // ブックのクローズ
            xlsxCreator.CloseBook(true);

            ts = sw.Elapsed;
            Console.WriteLine("ExcelCreator 8.0 for .NET 処理時間:{0}", ts.ToString());
            Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
            currentProcess.Refresh();
            Console.WriteLine("プロセス名   :" + currentProcess.ProcessName + "\n" +
                "物理メモリ使用量:" + (currentProcess.WorkingSet64 / 1024) + " KB\n" +
                "仮想メモリ使用量:" + (currentProcess.VirtualMemorySize64 / 1024) + " KB");
        }
        /// <summary>
        /// データを設定します。
        /// </summary>
        /// <param name="xlsxCreator"></param>
        private static void SetData(XlsxCreator xlsxCreator)
        {
            if (xlsxCreator == null) return;
            // データ
            xlsxCreator.Cell("B3").Value = "ExcelCreator 2012";
            xlsxCreator.Cell("C3").Value = 1;
            xlsxCreator.Cell("D3").Value = 63000;
            xlsxCreator.Cell("E3").Value = 63000;
            xlsxCreator.Cell("B4").Value = "VB-Report 7";
            xlsxCreator.Cell("C4").Value = 1;
            xlsxCreator.Cell("D4").Value = 81900;
            xlsxCreator.Cell("E4").Value = 81900;
            xlsxCreator.Cell("B5").Value = "ExcelCreator 8.0 for .NET によるデータの書き込み。(Strict Open XML 形式)";
        }
    }
}

既存のブックをオープンするには OpenBook メソッドを使用します。この場合、元のファイルの形式をそのまま引き継ぎます。



◆まとめ

Strict Open XML 形式と従来の Open XML 移行型 (Transitional) 形式は、現状ではわずかな違いですが、他のアプリケーションの互換等で使用されるケースが出てくる可能性はあると思いますので、引き続き動向を見ていきたいと思います。

Excel ブック (.xlsx) をプログラムで扱う – オープン

Open XML SDL 2.5 CTP 版と ExcelCreator を使用し、プログラム中から既存の Excel ブック (.xlsx) をオープンして目的のセルに値を設定する方法を紹介します。


◆検証環境
OS Windows 8(x64)
開発環境 Visual Studio 2012
CPU Intel(R) Core(TM)2 Duo E8400 @ 3.00GHz
メモリ 4GB
その他 SSD 搭載


◆Open XML SDK 2.5 を使用してブックをオープン

Visual Studio 2012 でコンソールアプリケーション「OXML25ConsoleApplication」を新規作成し、Open XML SDK 2.5 のアセンブリへの参照を追加してコードを述していきます。

ブックをオープンしてセルに値を設定するコード(Open XML SDK 2.5)

using System;
using System.Diagnostics;
using System.Linq;
using System.Drawing;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

namespace OXML25ConsoleApplication
{
    /// <summary>
    /// Program クラス
    /// </summary>
    class Program
    {
        /// <summary>
        /// private メンバ
        /// </summary>
        private static SpreadsheetDocument spreadsheetDocument = null;
        private static WorkbookPart workbookPart = null;
        private static WorksheetPart worksheetPart = null;
        private static SharedStringTablePart sharedStringPart = null;
        /// <summary>
        /// Main
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            TimeSpan ts = new TimeSpan();
            sw.Start();
            Console.WriteLine("Open XML SDK 2.5 による Excel (*.xlsx) ブックのオープン。");

            // SpreadsheetDocument をオープンします。
            spreadsheetDocument = SpreadsheetDocument.Open(@"明細.xlsx", true);

            // WorkbookPart を取得します。
            workbookPart = spreadsheetDocument.WorkbookPart;

            // WorksheetPart を取得します。
            IEnumerable<Sheet> sheets = spreadsheetDocument.WorkbookPart.Workbook.Descendants<Sheet>().Where
                (s => s.Name == "Sheet1");
            worksheetPart = (WorksheetPart)spreadsheetDocument.WorkbookPart.GetPartById(sheets.First().Id);

            // SharedStringTablePart を作成します。
            OpensharedStringPart();

            // データの設定
            SetData();

            // ワークブックを保存します。
            workbookPart.Workbook.Save();

            // ドキュメントをクローズします。
            spreadsheetDocument.Close();

            ts = sw.Elapsed;
            Console.WriteLine("Open XML SDK 2.5 処理時間:{0}", ts.ToString());
            Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
            currentProcess.Refresh();
            Console.WriteLine("プロセス名   :" + currentProcess.ProcessName + "\n" +
                "物理メモリ使用量:" + (currentProcess.WorkingSet64 / 1024) + " KB\n" +
                "仮想メモリ使用量:" + (currentProcess.VirtualMemorySize64 / 1024) + " KB");

        }
        /// <summary>
        /// データを設定します。
        /// </summary>
        /// <param name="sheet"></param>
        private static void SetData()
        {
            // データ
            SetValue("B", 3, "ExcelCreator 2012");
            SetValue("C", 3, 1);
            SetValue("D", 3, 63000);
            SetValue("E", 3, 63000);
            SetValue("B", 4, "VB-Report 7");
            SetValue("C", 4, 1);
            SetValue("D", 4, 81900);
            SetValue("E", 4, 81900);
            SetValue("B", 5, "Open XML SDK 2.5 CTP 版によるデータの書き込み。");
        }
        /// <summary>
        /// SharedStringTable を開く
        /// </summary>
        private static void OpensharedStringPart()
        {
            if (spreadsheetDocument == null) return;
            if (spreadsheetDocument.WorkbookPart.GetPartsOfType<SharedStringTablePart>().Count() > 0)
                sharedStringPart = spreadsheetDocument.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First();
            else
                sharedStringPart = spreadsheetDocument.WorkbookPart.AddNewPart<SharedStringTablePart>();
        }
        /// <summary>
        /// SharedStringTable への値の設定
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        private static int InsertSharedStringItem(string text)
        {
            if (sharedStringPart == null) return -1;
            // 共有文字列テーブルのデータがない場合新規で作成する。
            if (sharedStringPart.SharedStringTable == null)
                sharedStringPart.SharedStringTable = new SharedStringTable();
            int index = 0;
            foreach (SharedStringItem item in sharedStringPart.SharedStringTable.Elements<SharedStringItem>())
            {
                if (item.InnerText == text)
                    return index;
                index++;
            }
            // 共有文字列に文字を設定
            sharedStringPart.SharedStringTable.AppendChild(new SharedStringItem(new DocumentFormat.OpenXml.Spreadsheet.Text(text)));
            return index;
        }
        /// <summary>
        /// 値の設定
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="rowIndex"></param>
        /// <param name="value"></param>
        private static void SetValue(string columnName, int rowIndex, object value)
        {
            Type type = value.GetType();

            string valueString = "";
            if (value != null)
                valueString = value.ToString();
            Cell cell = InsertCellInWorksheet(columnName, rowIndex, -1);
            if (type == typeof(string))
            {
                // Insert the result into the SharedStringTablePart.
                int index = InsertSharedStringItem(valueString);

                cell.CellValue = new CellValue(index.ToString());
                cell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
            }
            else
            {
                cell.CellValue = new CellValue(valueString);
                cell.DataType = new EnumValue<CellValues>(CellValues.Number);
            }
            return;
        }
        /// <summary>
        /// セル情報の検索と取得(存在しない場合は新規追加)
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="rowIndex"></param>
        /// <param name="styleIndex"></param>
        /// <returns></returns>
        private static Cell InsertCellInWorksheet(string columnName, int rowIndex, int styleIndex)
        {
            if (worksheetPart == null) return null;
            Worksheet worksheet = worksheetPart.Worksheet;
            SheetData sheetData = worksheet.GetFirstChild<SheetData>();
            string cellReference = columnName + rowIndex.ToString();

            // 列情報があるかを確認し、無い場合は新規で作成する。
            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 refRow = null;
                foreach (Row r in sheetData.Elements<Row>())
                {
                    if (r.RowIndex > rowIndex)
                    {
                        refRow = r;
                        break;
                    }
                }
                row = new Row() { RowIndex = (uint)rowIndex };
                sheetData.InsertBefore(row, refRow);
            }

            // 列番号から、セルの存在を確認する。
            if (row.Elements<Cell>().Where(c => c.CellReference.Value == columnName + rowIndex.ToString()).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 (string.Compare(cell.CellReference, cellReference) > 0)
                    {
                        refCell = cell;
                        break;
                    }
                }
                Cell newCell = new Cell() { CellReference = cellReference };
                if (styleIndex >= 0) newCell.StyleIndex = new UInt32Value((uint)styleIndex);
                row.InsertBefore(newCell, refCell);
                return newCell;
            }
        }
    }
}

前回の新規作成と比べ、スタイルの追加が不要になるため若干コードが短くなりますが、それでも結構なコード量になります。WorkbookPart や WorksheetPart は既存のものを使用するため、新規作成時と比べて取得方法が異なります。行やセル情報は既存のものから検索して存在すればそのまま使用、なければ追加しますので、対象のセルが多い場合は処理速度が低下します。高速に処理を行うには、それらのデータをリストやツリーなど追加や検索に有利なデータ構造に展開して個別に実装する必要があるものと思われます。

また、Open XML SDK 2.5 でブックをオープンした場合、オープンしたブックを直接編集して保存するため、元のファイルを残したい場合はオープン前にコピーを作成する必要があります。


◆ExcelCreator を使用してブックをオープン

Visual Studio 2012 でコンソールアプリケーション「EC8ConsoleApplication」を新規作成し、ExcelCreator の各アセンブリへの参照および System.Drawing への参照を追加してコードを述していきます。

ブックをオープンしてセルに値を設定するコード(ExcelCreator 8.0 for .NET)

using System;
using System.Diagnostics;
using AdvanceSoftware.ExcelCreator;
using AdvanceSoftware.ExcelCreator.Xlsx;
using System.Drawing;

namespace EC8ConsoleApplication
{
    /// <summary>
    /// Program クラス
    /// </summary>
    class Program
    {
        /// <summary>
        /// Main
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            TimeSpan ts = new TimeSpan();
            sw.Start();
            Console.WriteLine("ExcelCreator 8.0 for .NET による Excel (*.xlsx) ブックのオープン。");

            var xlsxCreator = new XlsxCreator();
            // ブックのオープン
            xlsxCreator.OpenBook("EC8Open.xlsx", "明細.xlsx");
            // データの設定
            SetData(xlsxCreator);
            // ブックのクローズ
            xlsxCreator.CloseBook(true);

            ts = sw.Elapsed;
            Console.WriteLine("ExcelCreator 8.0 for .NET 処理時間:{0}", ts.ToString());
            Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
            currentProcess.Refresh();
            Console.WriteLine("プロセス名   :" + currentProcess.ProcessName + "\n" +
                "物理メモリ使用量:" + (currentProcess.WorkingSet64 / 1024) + " KB\n" +
                "仮想メモリ使用量:" + (currentProcess.VirtualMemorySize64 / 1024) + " KB");
        }
        /// <summary>
        /// データを設定します。
        /// </summary>
        /// <param name="xlsxCreator"></param>
        private static void SetData(XlsxCreator xlsxCreator)
        {
            if (xlsxCreator == null) return;
            // データ
            xlsxCreator.Cell("B3").Value = "ExcelCreator 2012";
            xlsxCreator.Cell("C3").Value = 1;
            xlsxCreator.Cell("D3").Value = 63000;
            xlsxCreator.Cell("E3").Value = 63000;
            xlsxCreator.Cell("B4").Value = "VB-Report 7";
            xlsxCreator.Cell("C4").Value = 1;
            xlsxCreator.Cell("D4").Value = 81900;
            xlsxCreator.Cell("E4").Value = 81900;
            xlsxCreator.Cell("B5").Value = "ExcelCreator 8.0 for .NET によるデータの書き込み。";
        }
    }
}

前回のコードからレイアウトの設定を省き、オープン用のメソッドに変更するだけで実装が可能です。Open XML SDK 2.5 と比べ、ブックやシートのパーツを個別に取得する必要がないため、シンプルなコードで処理が書けます。ExcelCreator では、オープン時の引数により既存のブックをオープンして上書きするか別ファイルに保存(オーバレイ)するか処理を選択できるため、元のファイルを残す場合も個別にコピーを作成する必要はありません。


◆まとめ

プログラム中からブックを扱う場合、ほとんどの場合において、新規にブックを作成するよりも既存のブックをオープンして目的のセルに値を入れていく使い方になると思われます。Open XML SDK 2.5 を使用する場合は、行やセル、スタイルの扱いにおいてある程度処理をクラス化、あるいはメソッド化しておかないとメンテナンスが大変そうです。また、大量のデータを処理する場合は、別途、行やセルのデータの管理に工夫が必要になります。処理速度については、いずれ比較検証を行いたいと思っています。

Excel ブック (.xlsx) をプログラムで扱う – 新規作成

今回はコンポーネントを使って Excel ブック (.xlsx) をプログラム中から新規に作成する方法を紹介します。前回は空のブックを新規に作成したので、追加で罫線や背景色、文字列や数値などを設定していきます。目標として画像のようなシンプルな Excel ブック (.xlsx) をプログラム中から新規に作成します。


◆検証環境
OS Windows 8(x64)
開発環境 Visual Studio 2012
CPU Intel(R) Core(TM)2 Duo E8400 @ 3.00GHz
メモリ 4GB
その他 SSD 搭載


◆Open XML SDK 2.5 を使用してブックを新規作成

Visual Studio 2012 でコンソールアプリケーション「OXML25ConsoleApplication」を新規作成し、Open XML SDK 2.5 のアセンブリへの参照を追加してコードを述していきます。

ブックを新規に作成するコード(Open XML SDK 2.5)

using System;
using System.Diagnostics;
using System.Linq;
using System.Drawing;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

namespace OXML25ConsoleApplication
{
    /// <summary>
    /// Program クラス
    /// </summary>
    class Program
    {
        /// <summary>
        /// private メンバ
        /// </summary>
        private static SpreadsheetDocument spreadsheetDocument = null;
        private static WorkbookPart workbookPart = null;
        private static WorksheetPart worksheetPart = null;
        private static WorkbookStylesPart workbookStylesPart = null;
        private static SharedStringTablePart sharedStringPart = null;
        /// <summary>
        /// Main
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            TimeSpan ts = new TimeSpan();
            sw.Start();
            Console.WriteLine("Open XML SDK 2.5 による Excel (*.xlsx) ブックの新規作成。");

            // SpreadsheetDocument を作成します。
            spreadsheetDocument = 
                SpreadsheetDocument.Create(@"OXMLCreate.xlsx", SpreadsheetDocumentType.Workbook);

            // WorkbookPart をドキュメントに追加します。
            workbookPart = spreadsheetDocument.AddWorkbookPart();
            workbookPart.Workbook = new Workbook();

            // WorksheetPart を WorkbookPart に追加します。
            worksheetPart = workbookPart.AddNewPart<WorksheetPart>();
            worksheetPart.Worksheet = new Worksheet(new SheetData());

            // WorkbookStylesPart を WorkbookPart に追加します。
            workbookStylesPart = workbookPart.AddNewPart<WorkbookStylesPart>();
            // 標準のスタイル情報を作成します。
            CreateDefaultStyles();

            // Sheets を Workbook に追加します。
            Sheets sheets = spreadsheetDocument.WorkbookPart.Workbook.
                AppendChild<Sheets>(new Sheets());

            // 新しい worksheet を workbook に追加します。
            Sheet sheet = new Sheet()
            {
                Id = spreadsheetDocument.WorkbookPart.
                    GetIdOfPart(worksheetPart),
                SheetId = 1,
                Name = "明細"
            };
            sheets.Append(sheet);

            // SharedStringTablePart を作成します。
            OpensharedStringPart();

            // レイアウトの設定
            SetLayout();
            // データの設定
            SetData();

            // ワークブックを保存します。
            workbookPart.Workbook.Save();

            // ドキュメントをクローズします。
            spreadsheetDocument.Close();

            ts = sw.Elapsed;
            Console.WriteLine("Open XML SDK 2.5 処理時間:{0}", ts.ToString());
            Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
            currentProcess.Refresh();
            Console.WriteLine("プロセス名   :" + currentProcess.ProcessName + "\n" +
                "物理メモリ使用量:" + (currentProcess.WorkingSet64 / 1024) + " KB\n" +
                "仮想メモリ使用量:" + (currentProcess.VirtualMemorySize64 / 1024) + " KB");

        }
        /// <summary>
        /// 標準のスタイル情報を作成します
        /// </summary>
        private static void CreateDefaultStyles()
        {
            Stylesheet stylesheet = new Stylesheet();
            // フォント
            Fonts fonts = new Fonts() { Count = (UInt32Value)2U };
            DocumentFormat.OpenXml.Spreadsheet.Font font1 = new DocumentFormat.OpenXml.Spreadsheet.Font();
            FontSize fontSize1 = new FontSize() { Val = 11D };
            DocumentFormat.OpenXml.Spreadsheet.Color color1 = new DocumentFormat.OpenXml.Spreadsheet.Color() { Theme = (UInt32Value)1U };
            FontName fontName1 = new FontName() { Val = "MS Pゴシック" };
            FontFamilyNumbering fontFamilyNumbering1 = new FontFamilyNumbering() { Val = 2 };
            FontScheme fontScheme1 = new FontScheme() { Val = FontSchemeValues.Minor };
            font1.Append(fontSize1);
            font1.Append(color1);
            font1.Append(fontName1);
            font1.Append(fontFamilyNumbering1);
            font1.Append(fontScheme1);
            DocumentFormat.OpenXml.Spreadsheet.Font font2 = new DocumentFormat.OpenXml.Spreadsheet.Font();
            FontSize fontSize2 = new FontSize() { Val = 11D };
            DocumentFormat.OpenXml.Spreadsheet.Color color2 = new DocumentFormat.OpenXml.Spreadsheet.Color() { Rgb = "FF006100" };
            FontName fontName2 = new FontName() { Val = "MS Pゴシック" };
            FontFamilyNumbering fontFamilyNumbering2 = new FontFamilyNumbering() { Val = 2 };
            FontScheme fontScheme2 = new FontScheme() { Val = FontSchemeValues.Minor };
            font2.Append(fontSize2);
            font2.Append(color2);
            font2.Append(fontName2);
            font2.Append(fontFamilyNumbering2);
            font2.Append(fontScheme2);
            fonts.Append(font1);
            fonts.Append(font2);
            // 塗りつぶし
            Fills fills = new Fills() { Count = (UInt32Value)2U };
            Fill fill1 = new Fill();
            PatternFill patternFill1 = new PatternFill() { PatternType = PatternValues.None };
            fill1.Append(patternFill1);
            Fill fill2 = new Fill();
            PatternFill patternFill2 = new PatternFill() { PatternType = PatternValues.Gray125 };
            fill2.Append(patternFill2);
            fills.Append(fill1);
            fills.Append(fill2);
            // 罫線
            Borders borders = new Borders() { Count = (UInt32Value)1U };
            Border border = new Border();
            LeftBorder leftBorder = new LeftBorder();
            RightBorder rightBorder = new RightBorder();
            TopBorder topBorder = new TopBorder();
            BottomBorder bottomBorder = new BottomBorder();
            DiagonalBorder diagonalBorder = new DiagonalBorder();
            border.Append(leftBorder);
            border.Append(rightBorder);
            border.Append(topBorder);
            border.Append(bottomBorder);
            border.Append(diagonalBorder);
            borders.Append(border);

            CellStyleFormats cellStyleFormats = new CellStyleFormats() { Count = (UInt32Value)1U };
            CellFormat cellFormat1 = new CellFormat() { NumberFormatId = (UInt32Value)0U, FontId = (UInt32Value)0U, FillId = (UInt32Value)0U, BorderId = (UInt32Value)0U };

            cellStyleFormats.Append(cellFormat1);

            CellFormats cellFormats = new CellFormats() { Count = (UInt32Value)1U };
            CellFormat cellFormat2 = new CellFormat() { NumberFormatId = (UInt32Value)0U, FontId = (UInt32Value)0U, FillId = (UInt32Value)0U, BorderId = (UInt32Value)0U, FormatId = (UInt32Value)0U };

            cellFormats.Append(cellFormat2);

            CellStyles cellStyles = new CellStyles() { Count = (UInt32Value)1U };
            CellStyle cellStyle = new CellStyle() { Name = "標準", FormatId = (UInt32Value)0U, BuiltinId = (UInt32Value)0U };

            cellStyles.Append(cellStyle);
            DifferentialFormats differentialFormats = new DifferentialFormats() { Count = (UInt32Value)0U };
            TableStyles tableStyles = new TableStyles() { Count = (UInt32Value)0U, DefaultTableStyle = "TableStyleMedium9", DefaultPivotStyle = "PivotStyleLight16" };

            stylesheet.Append(fonts);
            stylesheet.Append(fills);
            stylesheet.Append(borders);
            stylesheet.Append(cellStyleFormats);
            stylesheet.Append(cellFormats);
            stylesheet.Append(cellStyles);
            stylesheet.Append(differentialFormats);
            stylesheet.Append(tableStyles);
            workbookStylesPart.Stylesheet = stylesheet;
        }
        /// <summary>
        /// レイアウトを設定します。
        /// </summary>
        /// <param name="sheet"></param>
        private static void SetLayout()
        {
            // 罫線
            Border border = new Border()
            {
                BottomBorder = new BottomBorder()
                {
                    Style = DocumentFormat.OpenXml.Spreadsheet.BorderStyleValues.Medium,
                    Color = new DocumentFormat.OpenXml.Spreadsheet.Color() { Indexed = 12 }
                },
                LeftBorder = new LeftBorder()
                {
                    Style = DocumentFormat.OpenXml.Spreadsheet.BorderStyleValues.Medium,
                    Color = new DocumentFormat.OpenXml.Spreadsheet.Color() { Indexed = 12 }
                },
                RightBorder = new RightBorder()
                {
                    Style = DocumentFormat.OpenXml.Spreadsheet.BorderStyleValues.Medium,
                    Color = new DocumentFormat.OpenXml.Spreadsheet.Color() { Indexed = 12 }
                },
                TopBorder = new TopBorder()
                {
                    Style = DocumentFormat.OpenXml.Spreadsheet.BorderStyleValues.Medium,
                    Color = new DocumentFormat.OpenXml.Spreadsheet.Color() { Indexed = 12 }
                }
            };
            // 罫線情報を追加
            int count = workbookStylesPart.Stylesheet.Borders.Count();
            workbookStylesPart.Stylesheet.Borders.Append(border);
            workbookStylesPart.Stylesheet.Borders.Count = new UInt32Value((uint)++count);
            // 塗りつぶし情報を追加
            int fillCount = workbookStylesPart.Stylesheet.Fills.Count();
            Fill fill = new Fill();
            PatternFill patternFill = new PatternFill() { PatternType = PatternValues.Solid, ForegroundColor = new DocumentFormat.OpenXml.Spreadsheet.ForegroundColor() { Indexed = 12 } };
            fill.Append(patternFill);
            workbookStylesPart.Stylesheet.Fills.Append(fill);
            workbookStylesPart.Stylesheet.Fills.Count = new UInt32Value((uint)++fillCount);
            // フォント情報を追加
            int fontCount = workbookStylesPart.Stylesheet.Fonts.Count();
            DocumentFormat.OpenXml.Spreadsheet.Font font = new DocumentFormat.OpenXml.Spreadsheet.Font();
            FontSize fontSize = new FontSize() { Val = 11D };
            DocumentFormat.OpenXml.Spreadsheet.Color color = new DocumentFormat.OpenXml.Spreadsheet.Color() { Rgb = "FFFFFFFF" };
            FontName fontName = new FontName() { Val = "MS Pゴシック" };
            FontFamilyNumbering fontFamilyNumbering = new FontFamilyNumbering() { Val = 2 };
            FontScheme fontScheme = new FontScheme() { Val = FontSchemeValues.Minor };
            font.Append(fontSize);
            font.Append(color);
            font.Append(fontName);
            font.Append(fontFamilyNumbering);
            font.Append(fontScheme);
            workbookStylesPart.Stylesheet.Fonts.Append(font);
            workbookStylesPart.Stylesheet.Fonts.Count = new UInt32Value((uint)++fontCount);
            // 属性を追加
            CellFormat cellFormat = new CellFormat() { NumberFormatId = (UInt32Value)0U, FontId = (UInt32Value)2U, FillId = (UInt32Value)2U, BorderId = (UInt32Value)0U, ApplyNumberFormat = false, ApplyBorder = true, ApplyAlignment = false, ApplyProtection = false };
            count = workbookStylesPart.Stylesheet.CellFormats.Count();
            workbookStylesPart.Stylesheet.CellFormats.Append(cellFormat);
            workbookStylesPart.Stylesheet.CellFormats.Count = new UInt32Value((uint)++count);
            // スタイルをセルに設定
            InsertCellInWorksheet("B", 2, count - 1);
            InsertCellInWorksheet("C", 2, count - 1);
            InsertCellInWorksheet("D", 2, count - 1);
            InsertCellInWorksheet("E", 2, count - 1);
            // 属性を追加
            cellFormat = new CellFormat() { NumberFormatId = (UInt32Value)0U, FontId = (UInt32Value)0U, FillId = (UInt32Value)0U, BorderId = (UInt32Value)1U, ApplyNumberFormat = false, ApplyBorder = true, ApplyAlignment = false, ApplyProtection = false };
            count = workbookStylesPart.Stylesheet.CellFormats.Count();
            workbookStylesPart.Stylesheet.CellFormats.Append(cellFormat);
            workbookStylesPart.Stylesheet.CellFormats.Count = new UInt32Value((uint)++count);
            // スタイルをセルに設定
            for (int i = 3; i <= 4; i++)
            {
                InsertCellInWorksheet("B", i, count - 1);
                InsertCellInWorksheet("C", i, count - 1);
                InsertCellInWorksheet("D", i, count - 1);
                InsertCellInWorksheet("E", i, count - 1);
            }
            // タイトル行
            SetValue("B", 2, "商品名");
            SetValue("C", 2, "数量");
            SetValue("D", 2, "単価");
            SetValue("E", 2, "金額");
        }
        /// <summary>
        /// データを設定します。
        /// </summary>
        /// <param name="sheet"></param>
        private static void SetData()
        {
            // データ
            SetValue("B", 3, "ExcelCreator 2012");
            SetValue("C", 3, 1);
            SetValue("D", 3, 63000);
            SetValue("E", 3, 63000);
            SetValue("B", 4, "VB-Report 7");
            SetValue("C", 4, 1);
            SetValue("D", 4, 81900);
            SetValue("E", 4, 81900);
        }
        /// <summary>
        /// SharedStringTable を開く
        /// </summary>
        private static void OpensharedStringPart()
        {
            if (spreadsheetDocument == null) return;
            if (spreadsheetDocument.WorkbookPart.GetPartsOfType<SharedStringTablePart>().Count() > 0)
                sharedStringPart = spreadsheetDocument.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First();
            else
                sharedStringPart = spreadsheetDocument.WorkbookPart.AddNewPart<SharedStringTablePart>();
        }
        /// <summary>
        /// SharedStringTable への値の設定
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        private static int InsertSharedStringItem(string text)
        {
            if (sharedStringPart == null) return -1;
            // 共有文字列テーブルのデータがない場合新規で作成する。
            if (sharedStringPart.SharedStringTable == null)
                sharedStringPart.SharedStringTable = new SharedStringTable();
            int index = 0;
            foreach (SharedStringItem item in sharedStringPart.SharedStringTable.Elements<SharedStringItem>())
            {
                if (item.InnerText == text)
                    return index;
                index++;
            }
            // 共有文字列に文字を設定
            sharedStringPart.SharedStringTable.AppendChild(new SharedStringItem(new DocumentFormat.OpenXml.Spreadsheet.Text(text)));
            return index;
        }
        /// <summary>
        /// 値の設定
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="rowIndex"></param>
        /// <param name="value"></param>
        private static void SetValue(string columnName, int rowIndex, object value)
        {
            Type type = value.GetType();

            string valueString = "";
            if (value != null)
                valueString = value.ToString();
            Cell cell = InsertCellInWorksheet(columnName, rowIndex, -1);
            if (type == typeof(string))
            {
                // Insert the result into the SharedStringTablePart.
                int index = InsertSharedStringItem(valueString);

                cell.CellValue = new CellValue(index.ToString());
                cell.DataType = new EnumValue<CellValues>(CellValues.SharedString);
            }
            else
            {
                cell.CellValue = new CellValue(valueString);
                cell.DataType = new EnumValue<CellValues>(CellValues.Number);
            }
            return;
        }
        /// <summary>
        /// セル情報の検索と取得(存在しない場合は新規追加)
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="rowIndex"></param>
        /// <param name="styleIndex"></param>
        /// <returns></returns>
        private static Cell InsertCellInWorksheet(string columnName, int rowIndex, int styleIndex)
        {
            if (worksheetPart == null) return null;
            Worksheet worksheet = worksheetPart.Worksheet;
            SheetData sheetData = worksheet.GetFirstChild<SheetData>();
            string cellReference = columnName + rowIndex.ToString();

            // 列情報があるかを確認し、無い場合は新規で作成する。
            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 refRow = null;
                foreach (Row r in sheetData.Elements<Row>())
                {
                    if (r.RowIndex > rowIndex)
                    {
                        refRow = r;
                        break;
                    }
                }
                row = new Row() { RowIndex = (uint)rowIndex };
                sheetData.InsertBefore(row, refRow);
            }

            // 列番号から、セルの存在を確認する。
            if (row.Elements<Cell>().Where(c => c.CellReference.Value == columnName + rowIndex.ToString()).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 (string.Compare(cell.CellReference, cellReference) > 0)
                    {
                        refCell = cell;
                        break;
                    }
                }
                Cell newCell = new Cell() { CellReference = cellReference };
                if (styleIndex >= 0) newCell.StyleIndex = new UInt32Value((uint)styleIndex);
                row.InsertBefore(newCell, refCell);
                return newCell;
            }
        }
    }
}

ワークブックに対してシートやスタイル情報等のパーツを追加していく手順となります。スタイルの追加では、フォントや罫線、塗りつぶし情報を追加した上で、それらの組み合わせでセルのスタイルを追加してそのインデックス番号をセル情報の”s”タグに設定します。今回は省略しましたが、スタイルを設定する場合、本来は既存のスタイル情報とのマッチングを行い、すでに存在する場合はそのスタイル番号を指定する必要があります。フォント、罫線、塗りつぶしそれぞれでマッチングを行う必要があるため、全てのスタイル情報を扱うには相当なコード量となるものと思われます。

データの設定に関しても既存の行やセル情報とのマッチングが必須となり、データ量が多くなる場合、比較において高速な処理が求められます。また、文字列は別の構造で管理されるため、個別の処理が必要です。


◆ExcelCreator を使用してブックを新規作成

Visual Studio 2012 でコンソールアプリケーション「EC8ConsoleApplication」を新規作成し、ExcelCreator の各アセンブリへの参照および System.Drawing への参照を追加してコードを述していきます。

ブックを新規に作成するコード(ExcelCreator 8.0 for .NET)

using System;
using System.Diagnostics;
using AdvanceSoftware.ExcelCreator;
using AdvanceSoftware.ExcelCreator.Xlsx;
using System.Drawing;

namespace EC8ConsoleApplication
{
    /// <summary>
    /// Program クラス
    /// </summary>
    class Program
    {
        /// <summary>
        /// Main
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            TimeSpan ts = new TimeSpan();
            sw.Start();
            Console.WriteLine("ExcelCreator 8.0 for .NET による Excel (*.xlsx) ブックの新規作成。");

            var xlsxCreator = new XlsxCreator();
            // ブックの新規作成
            xlsxCreator.CreateBook("EC8Create.xlsx", 1, xlsxVersion.ver2010);
            // シート名の設定
            xlsxCreator.SheetName = "明細";
            // レイアウトの設定
            SetLayout(xlsxCreator);
            // データの設定
            SetData(xlsxCreator);
            // ブックのクローズ
            xlsxCreator.CloseBook(true);

            ts = sw.Elapsed;
            Console.WriteLine("ExcelCreator 8.0 for .NET 処理時間:{0}", ts.ToString());
            Process currentProcess = System.Diagnostics.Process.GetCurrentProcess();
            currentProcess.Refresh();
            Console.WriteLine("プロセス名   :" + currentProcess.ProcessName + "\n" +
                "物理メモリ使用量:" + (currentProcess.WorkingSet64 / 1024) + " KB\n" +
                "仮想メモリ使用量:" + (currentProcess.VirtualMemorySize64 / 1024) + " KB");

        }
        /// <summary>
        /// レイアウトを設定します。
        /// </summary>
        /// <param name="xlsxCreator"></param>
        private static void SetLayout(XlsxCreator xlsxCreator)
        {
            if (xlsxCreator == null) return;
            // 罫線
            xlsxCreator.Cell("B2:E4").Attr.Box(BoxType.Ltc, BorderStyle.Medium, xlColor.Blue);
            // 背景色
            xlsxCreator.Cell("B2:E2").Attr.BackColor = Color.Blue;
            // タイトル行
            xlsxCreator.Cell("B2:E2").Attr.FontColor = Color.White;
            xlsxCreator.Cell("B2").Value = "商品名";
            xlsxCreator.Cell("C2").Value = "数量";
            xlsxCreator.Cell("D2").Value = "単価";
            xlsxCreator.Cell("E2").Value = "金額";
        }
        /// <summary>
        /// データを設定します。
        /// </summary>
        /// <param name="xlsxCreator"></param>
        private static void SetData(XlsxCreator xlsxCreator)
        {
            if (xlsxCreator == null) return;
            // データ
            xlsxCreator.Cell("B3").Value = "ExcelCreator 2012";
            xlsxCreator.Cell("C3").Value = 1;
            xlsxCreator.Cell("D3").Value = 63000;
            xlsxCreator.Cell("E3").Value = 63000;
            xlsxCreator.Cell("B4").Value = "VB-Report 7";
            xlsxCreator.Cell("C4").Value = 1;
            xlsxCreator.Cell("D4").Value = 81900;
            xlsxCreator.Cell("E4").Value = 81900;
        }
    }
}

Open XML SDK 2.5 と比べると少しコードが短くなり、必要最小限の設定で目的のブックを作成することができます。xls 形式のプログラムと比べてもよく似たコーディングでブックの作成ができるため、両形式をサポートするプログラムを作成する場合も最小限の変更で対応ができます。色の指定では System.Drawing.Color を使用したプロパティ、メソッドがサポートされます。


◆まとめ

Open XML SDK では、提供されるクラスやプロパティ、メソッドが細かく構造化されていて、xlsx 形式のファイルを細かく扱うことが可能です。しかしながら、それらのクラスを効率よく扱うにはデータ構造にかなりの工夫が必要で、ブックやクラスの構造を熟知する必要があります。

明けましておめでとうございます。

明けましておめでとうございます。
引き続き Excel ファイルに関する技術情報を書いてゆきたいと思います。
今年も宜しくお願い致します。

Excel ブック (.xlsx) をプログラムで扱う – 準備 2


◆Excel ブック (.xlsx) をプログラムで扱う

前回は「Open XML SDK 2.5」を使用する準備と、作成したブックについて紹介しましたので、今回はアドバンスソフトウェアの「ExcelCreator 8.0 for .NET」を使用して Excel ブック (.xlsx) を作成する準備と作成したブックについて紹介します。


◆検証環境
OS Windows 8(x64)
開発環境 Visual Studio 2012
CPU Intel(R) Core(TM)2 Duo E8400 @ 3.00GHz
メモリ 4GB
その他 SSD 搭載


◆ExcelCreator 体験版のダウンロードとインストール

ExcelCreator は、アドバンスソフトウェア株式会社が開発販売するコンポーネントです。.NET 環境で xlsx 形式のブックを使用した開発を行う場合、「ExcelCreator 8.0 for .NET」を使用します。

ExcelCreator 8.0 for .NET は、下記のサイトからダウンロードできます。

http://www.adv.co.jp/download/download.php?ftype=D

ExcelCreator8Demo_1627.exe(2012.12.21 現在)をダウンロード、実行してインストールを行います。


◆プロジェクトの作成と参照の追加

次に Visual Studio 2012 を起動し、コンソールアプリケーション「EC8ConsoleApplication」を作成します。参照の追加で先ほどインストールした ExcelCreator 8.0 for .NET のアセンブリを追加します。ExcelCreator 8.0 for .NET には、.NET Framework 4 用のアセンブリと 2.0 用のアセンブリが用意されています。今回は .NET Framework 4 用のアセンブリを使用します。



Excel ブック (.xlsx) を新規に作成するコード(ExcelCreator 8.0 for .NET)

using AdvanceSoftware.ExcelCreator;
using AdvanceSoftware.ExcelCreator.Xlsx;

namespace EC8ConsoleApplication
{
    /// <summary>
    /// Program クラス
    /// </summary>
    class Program
    {
        /// <summary>
        /// Main
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            // XlsxCreator インスタンス生成
            XlsxCreator xlsxCreator = new XlsxCreator();
            // ブックの新規作成
            xlsxCreator.CreateBook(@"EC8Create.xlsx", 1, xlsxVersion.ver2007);
            // ブックのクローズ
            xlsxCreator.CloseBook(true);
        }
    }
}

Open XML SDK を使用した場合と比べ、随分コードが短くなりました。CreateBook メソッドの 3 番目の引数で作成するブックのバージョンを指定することができます。バージョン指定を変更すると、docProps/app.xml の AppVersion タグの値や xl/workbook.xml の fileVersion タグの各属性が変わります。

作成したブックの拡張子を .zip に変更し、解凍して構造を確認します。


XML ファイル一覧

  • [Content_Types].xml
  • _rels/.rels
  • docProps/app.xml
  • docProps/core.xml
  • xl/_rels/workbook.xml.rels
  • xl/workbook.xml
  • xl/worksheets/sheet.xml
  • xl/styles.xml
  • xl/theme/theme1.xml

Excel で作成した場合と同じ構成で作成されています。
また、作成されたブックを解凍して中の XML ファイルを確認します。

[Content_Types].xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml" />
<Default Extension="xml" ContentType="application/xml" />
<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml" />
<Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml" />
<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" />
<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml" />
<Override PartName="/xl/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml" />
<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" />
</Types>


_rels/.rels

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="xl/workbook.xml" />
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml" />
<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml" />
</Relationships>


docProps/app.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Properties xmlns="http://schemas.openxmlformats.org/officeDocument/2006/extended-properties" xmlns:vt="http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes">
<Application>Microsoft Excel</Application>
<DocSecurity>0</DocSecurity>
<ScaleCrop>false</ScaleCrop>
<HeadingPairs>
<vt:vector size="2" baseType="variant">
<vt:variant>
<vt:lpstr>ワークシート</vt:lpstr>
</vt:variant>
<vt:variant>
<vt:i4>1</vt:i4>
</vt:variant>
</vt:vector>
</HeadingPairs>
<TitlesOfParts>
<vt:vector size="1" baseType="lpstr">
<vt:lpstr>Sheet1</vt:lpstr>
</vt:vector>
</TitlesOfParts>
<Company>
</Company>
<LinksUpToDate>false</LinksUpToDate>
<SharedDoc>false</SharedDoc>
<HyperlinksChanged>false</HyperlinksChanged>
<AppVersion>12.0000</AppVersion>
</Properties>


docProps/core.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<dc:creator></dc:creator>
<cp:lastModifiedBy></cp:lastModifiedBy>
<dcterms:created xsi:type="dcterms:W3CDTF">
2006-11-16T00:13:03Z</dcterms:created>
<dcterms:modified xsi:type="dcterms:W3CDTF">
2006-11-16T00:13:46Z</dcterms:modified>
</cp:coreProperties>
[/plain]
</p>
<BR>

<strong>xl/styles.xml</strong>
<p>
1
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<styleSheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<fonts count="2">
<font>
<sz val="11" />
<color theme="1" />
<name val="MS Pゴシック" />
<family val="2" />
<charset val="128" />
<scheme val="minor" />
</font>
<font>
<sz val="6" />
<name val="MS Pゴシック" />
<family val="2" />
<charset val="128" />
<scheme val="minor" />
</font>
</fonts>
<fills count="2">
<fill>
<patternFill patternType="none" />
</fill>
<fill>
<patternFill patternType="gray125" />
</fill>
</fills>
<borders count="1">
<border>
<left />
<right />
<top />
<bottom />
<diagonal />
</border>
</borders>
<cellStyleXfs count="1">
<xf numFmtId="0" fontId="0" fillId="0" borderId="0">
<alignment vertical="center" />
</xf>
</cellStyleXfs>
<cellXfs count="1">
<xf numFmtId="0" fontId="0" fillId="0" borderId="0" xfId="0">
<alignment vertical="center" />
</xf>
</cellXfs>
<cellStyles count="1">
<cellStyle name="標準" xfId="0" builtinId="0" />
</cellStyles>
<dxfs count="0" />
<tableStyles count="0" defaultTableStyle="TableStyleMedium9" defaultPivotStyle="PivotStyleLight16" />
</styleSheet>


xl/workbook.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
<fileVersion appName="xl" lastEdited="4" lowestEdited="4" rupBuild="4505" />
<workbookPr defaultThemeVersion="124226" />
<bookViews>
<workbookView xWindow="600" yWindow="30" windowWidth="18135" windowHeight="11985" />
</bookViews>
<sheets>
<sheet name="Sheet1" sheetId="1" r:id="rId3" />
</sheets>
<calcPr calcId="124519" />
</workbook>


xl/_rels/workbook.xml.rels

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml" />
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml" />
<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml" />
</Relationships>


xl/theme/theme1.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" name="Office テーマ">
<a:themeElements>
<a:clrScheme name="Office">
<a:dk1>
<a:sysClr val="windowText" lastClr="000000" />
</a:dk1>
<a:lt1>
<a:sysClr val="window" lastClr="FFFFFF" />
</a:lt1>
<a:dk2>
<a:srgbClr val="1F497D" />
</a:dk2>
<a:lt2>
<a:srgbClr val="EEECE1" />
</a:lt2>
<a:accent1>
<a:srgbClr val="4F81BD" />
</a:accent1>
<a:accent2>
<a:srgbClr val="C0504D" />
</a:accent2>
<a:accent3>
<a:srgbClr val="9BBB59" />
</a:accent3>
<a:accent4>
<a:srgbClr val="8064A2" />
</a:accent4>
<a:accent5>
<a:srgbClr val="4BACC6" />
</a:accent5>
<a:accent6>
<a:srgbClr val="F79646" />
</a:accent6>
<a:hlink>
<a:srgbClr val="0000FF" />
</a:hlink>
<a:folHlink>
<a:srgbClr val="800080" />
</a:folHlink>
</a:clrScheme>
<a:fontScheme name="Office">
<a:majorFont>
<a:latin typeface="Cambria" />
<a:ea typeface="" />
<a:cs typeface="" />
<a:font script="Jpan" typeface="MS Pゴシック" />
<a:font script="Hang" typeface="ハングル" />
<a:font script="Hans" typeface="宋体" />
<a:font script="Hant" typeface="新細明體" />
<a:font script="Arab" typeface="Times New Roman" />
<a:font script="Hebr" typeface="Times New Roman" />
<a:font script="Thai" typeface="Tahoma" />
<a:font script="Ethi" typeface="Nyala" />
<a:font script="Beng" typeface="Vrinda" />
<a:font script="Gujr" typeface="Shruti" />
<a:font script="Khmr" typeface="MoolBoran" />
<a:font script="Knda" typeface="Tunga" />
<a:font script="Guru" typeface="Raavi" />
<a:font script="Cans" typeface="Euphemia" />
<a:font script="Cher" typeface="Plantagenet Cherokee" />
<a:font script="Yiii" typeface="Microsoft Yi Baiti" />
<a:font script="Tibt" typeface="Microsoft Himalaya" />
<a:font script="Thaa" typeface="MV Boli" />
<a:font script="Deva" typeface="Mangal" />
<a:font script="Telu" typeface="Gautami" />
<a:font script="Taml" typeface="Latha" />
<a:font script="Syrc" typeface="Estrangelo Edessa" />
<a:font script="Orya" typeface="Kalinga" />
<a:font script="Mlym" typeface="Kartika" />
<a:font script="Laoo" typeface="DokChampa" />
<a:font script="Sinh" typeface="Iskoola Pota" />
<a:font script="Mong" typeface="Mongolian Baiti" />
<a:font script="Viet" typeface="Times New Roman" />
<a:font script="Uigh" typeface="Microsoft Uighur" />
</a:majorFont>
<a:minorFont>
<a:latin typeface="Calibri" />
<a:ea typeface="" />
<a:cs typeface="" />
<a:font script="Jpan" typeface="MS Pゴシック" />
<a:font script="Hang" typeface="ハングル" />
<a:font script="Hans" typeface="宋体" />
<a:font script="Hant" typeface="新細明體" />
<a:font script="Arab" typeface="Arial" />
<a:font script="Hebr" typeface="Arial" />
<a:font script="Thai" typeface="Tahoma" />
<a:font script="Ethi" typeface="Nyala" />
<a:font script="Beng" typeface="Vrinda" />
<a:font script="Gujr" typeface="Shruti" />
<a:font script="Khmr" typeface="DaunPenh" />
<a:font script="Knda" typeface="Tunga" />
<a:font script="Guru" typeface="Raavi" />
<a:font script="Cans" typeface="Euphemia" />
<a:font script="Cher" typeface="Plantagenet Cherokee" />
<a:font script="Yiii" typeface="Microsoft Yi Baiti" />
<a:font script="Tibt" typeface="Microsoft Himalaya" />
<a:font script="Thaa" typeface="MV Boli" />
<a:font script="Deva" typeface="Mangal" />
<a:font script="Telu" typeface="Gautami" />
<a:font script="Taml" typeface="Latha" />
<a:font script="Syrc" typeface="Estrangelo Edessa" />
<a:font script="Orya" typeface="Kalinga" />
<a:font script="Mlym" typeface="Kartika" />
<a:font script="Laoo" typeface="DokChampa" />
<a:font script="Sinh" typeface="Iskoola Pota" />
<a:font script="Mong" typeface="Mongolian Baiti" />
<a:font script="Viet" typeface="Arial" />
<a:font script="Uigh" typeface="Microsoft Uighur" />
</a:minorFont>
</a:fontScheme>
<a:fmtScheme name="Office">
<a:fillStyleLst>
<a:solidFill>
<a:schemeClr val="phClr" />
</a:solidFill>
<a:gradFill rotWithShape="1">
<a:gsLst>
<a:gs pos="0">
<a:schemeClr val="phClr">
<a:tint val="50000" />
<a:satMod val="300000" />
</a:schemeClr>
</a:gs>
<a:gs pos="35000">
<a:schemeClr val="phClr">
<a:tint val="37000" />
<a:satMod val="300000" />
</a:schemeClr>
</a:gs>
<a:gs pos="100000">
<a:schemeClr val="phClr">
<a:tint val="15000" />
<a:satMod val="350000" />
</a:schemeClr>
</a:gs>
</a:gsLst>
<a:lin ang="16200000" scaled="1" />
</a:gradFill>
<a:gradFill rotWithShape="1">
<a:gsLst>
<a:gs pos="0">
<a:schemeClr val="phClr">
<a:shade val="51000" />
<a:satMod val="130000" />
</a:schemeClr>
</a:gs>
<a:gs pos="80000">
<a:schemeClr val="phClr">
<a:shade val="93000" />
<a:satMod val="130000" />
</a:schemeClr>
</a:gs>
<a:gs pos="100000">
<a:schemeClr val="phClr">
<a:shade val="94000" />
<a:satMod val="135000" />
</a:schemeClr>
</a:gs>
</a:gsLst>
<a:lin ang="16200000" scaled="0" />
</a:gradFill>
</a:fillStyleLst>
<a:lnStyleLst>
<a:ln w="9525" cap="flat" cmpd="sng" algn="ctr">
<a:solidFill>
<a:schemeClr val="phClr">
<a:shade val="95000" />
<a:satMod val="105000" />
</a:schemeClr>
</a:solidFill>
<a:prstDash val="solid" />
</a:ln>
<a:ln w="25400" cap="flat" cmpd="sng" algn="ctr">
<a:solidFill>
<a:schemeClr val="phClr" />
</a:solidFill>
<a:prstDash val="solid" />
</a:ln>
<a:ln w="38100" cap="flat" cmpd="sng" algn="ctr">
<a:solidFill>
<a:schemeClr val="phClr" />
</a:solidFill>
<a:prstDash val="solid" />
</a:ln>
</a:lnStyleLst>
<a:effectStyleLst>
<a:effectStyle>
<a:effectLst>
<a:outerShdw blurRad="40000" dist="20000" dir="5400000" rotWithShape="0">
<a:srgbClr val="000000">
<a:alpha val="38000" />
</a:srgbClr>
</a:outerShdw>
</a:effectLst>
</a:effectStyle>
<a:effectStyle>
<a:effectLst>
<a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0">
<a:srgbClr val="000000">
<a:alpha val="35000" />
</a:srgbClr>
</a:outerShdw>
</a:effectLst>
</a:effectStyle>
<a:effectStyle>
<a:effectLst>
<a:outerShdw blurRad="40000" dist="23000" dir="5400000" rotWithShape="0">
<a:srgbClr val="000000">
<a:alpha val="35000" />
</a:srgbClr>
</a:outerShdw>
</a:effectLst>
<a:scene3d>
<a:camera prst="orthographicFront">
<a:rot lat="0" lon="0" rev="0" />
</a:camera>
<a:lightRig rig="threePt" dir="t">
<a:rot lat="0" lon="0" rev="1200000" />
</a:lightRig>
</a:scene3d>
<a:sp3d>
<a:bevelT w="63500" h="25400" />
</a:sp3d>
</a:effectStyle>
</a:effectStyleLst>
<a:bgFillStyleLst>
<a:solidFill>
<a:schemeClr val="phClr" />
</a:solidFill>
<a:gradFill rotWithShape="1">
<a:gsLst>
<a:gs pos="0">
<a:schemeClr val="phClr">
<a:tint val="40000" />
<a:satMod val="350000" />
</a:schemeClr>
</a:gs>
<a:gs pos="40000">
<a:schemeClr val="phClr">
<a:tint val="45000" />
<a:shade val="99000" />
<a:satMod val="350000" />
</a:schemeClr>
</a:gs>
<a:gs pos="100000">
<a:schemeClr val="phClr">
<a:shade val="20000" />
<a:satMod val="255000" />
</a:schemeClr>
</a:gs>
</a:gsLst>
<a:path path="circle">
<a:fillToRect l="50000" t="-80000" r="50000" b="180000" />
</a:path>
</a:gradFill>
<a:gradFill rotWithShape="1">
<a:gsLst>
<a:gs pos="0">
<a:schemeClr val="phClr">
<a:tint val="80000" />
<a:satMod val="300000" />
</a:schemeClr>
</a:gs>
<a:gs pos="100000">
<a:schemeClr val="phClr">
<a:shade val="30000" />
<a:satMod val="200000" />
</a:schemeClr>
</a:gs>
</a:gsLst>
<a:path path="circle">
<a:fillToRect l="50000" t="50000" r="50000" b="50000" />
</a:path>
</a:gradFill>
</a:bgFillStyleLst>
</a:fmtScheme>
</a:themeElements>
<a:objectDefaults />
<a:extraClrSchemeLst />
</a:theme>


xl/worksheets/sheet.xml

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
<dimension ref="A1" />
<sheetViews>
<sheetView workbookViewId="0" />
</sheetViews>
<sheetFormatPr defaultRowHeight="13.5" />
<sheetData />
<phoneticPr fontId="1" />
<pageMargins left="0.7" right="0.7" top="0.75" bottom="0.75" header="0.3" footer="0.3" />
</worksheet>


xl/_rels/workbook.xml.rels

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="theme/theme1.xml" />
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" Target="styles.xml" />
<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/worksheet" Target="worksheets/sheet1.xml" />
</Relationships>

いずれのファイルも Excel で作成した場合とほとんど同じ内容で作成されています。


次回はそれぞれのコンポーネントを使用して新規にブックを作成する方法について詳しく見ていきたいと思います。