LoginSignup
31
31

More than 5 years have passed since last update.

C#でOpenXMLを使ったExcelの読み込み

Last updated at Posted at 2015-01-21

サンプル

OpenXMLを使いExcelを読み込みタブ区切りでConsoleに出力するサンプルを作成した。
参考にしたページは下記の通り。

環境は下記のとおり。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

namespace SampleOpenXML
{
    class Program
    {
        static void Main(string[] args)
        {
            var fileName = @"C:\Users\LocalUser\Documents\sampleOpenXML.xlsx";

            using (SpreadsheetDocument document = SpreadsheetDocument.Open(fileName, false))
            {
                var wbPart = document.WorkbookPart;
                var stringTable = wbPart.GetPartsOfType<SharedStringTablePart>().FirstOrDefault();
                foreach (var sheet in wbPart.Workbook.Descendants<Sheet>())
                {
                    if (sheet.Name == "Sheet1")
                    {
                        var wsheetPart = wbPart.GetPartById(sheet.Id) as WorksheetPart;
                        if (wsheetPart == null)
                        {
                            Console.WriteLine("WorksheetPart Not Found !!");
                            return;
                        }

                        var ws = wsheetPart.Worksheet;
                        foreach (var row in ws.Descendants<Row>())
                        {
                            var list = new List<string>();
                            foreach (Cell cell in row)
                            {

                                string value = cell.InnerText;
                                if (cell.DataType != null)
                                {
                                    switch (cell.DataType.Value)
                                    {
                                        case CellValues.Boolean:
                                        case CellValues.Date:
                                        case CellValues.Error:
                                        case CellValues.InlineString:
                                        case CellValues.Number:
                                        case CellValues.String:
                                            value = cell.InnerText;
                                            break;
                                        case CellValues.SharedString:
                                            if (stringTable != null)
                                                value = stringTable.SharedStringTable.ElementAt(int.Parse(value)).InnerText;
                                            break;
                                        default:
                                            break;
                                    }
                                }
                                list.Add(value);
                            }
                            Console.WriteLine(string.Join("\t", list.ToArray()));
                        }
                    }
                }
            }
        }
    }
}

その後

その後、実際のデータを取り込んだところ漢字文字列がカタカナ付きで取得された。例えば「内科」とExcelには表示されているが「内科ナイカ」と取得された。
SharedStringTable から取得するとき、下記のように変更した。

    if (stringTable != null)
    {
        var element = stringTable.SharedStringTable.ElementAt(int.Parse(value));
        value = element.FirstChaid.InnerText;
    }

その後のその後

その後のその後、数式のCellを取り込もうとすると、数式と値が同時に取得されたり、文字列が分かれて格納されていることがわかり下記のような関数を作成した。

        private static string GetCellValue(Cell cell, SharedStringTable sTable)
        {
            string value = cell.InnerText;

            // 式が入っている場合
            if (cell.CellFormula != null)
                return cell.CellValue.Text;

            // データタイプ、SharedStringTableがnull、DataTypeがSharedString以外
            if (cell.DataType == null || sTable == null)
                return value;
            if (cell.DataType.Value != CellValues.SharedString)
                return value;

            var element = sTable.ElementAt(int.Parse(value));

            // 子Nodeがなければ、最初のNodeの値を返す
            if (!element.HasChildren)
                return element.FirstChild.InnerText;

            // 子Nodeからデータを取得し結合して返す
            var sb = new StringBuilder();
            foreach (var node in element.ChildElements)
            {
                switch (node.LocalName)
                {
                    case "t":
                    case "r":
                        sb.Append(node.InnerText);
                        break;
                }
            }
            return sb.ToString();
        }

読み込みは下記のように変更した。

                        foreach (Cell cell in row)
                        {
                            list.Add(GetCellValue(cell, stringTable));
                        }

日付の取得

日付の取得は、DateTime.DateTimeOADateを使用してDateTimeに変換する。

31
31
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
31