.net使用openxml读取excel中的数据【Demo】

下是一个简单的示例代码,用于使用 OpenXML 读取 Excel 文件中的数据:

using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using System;
using System.Collections.Generic;
using System.IO;

class Program
{
    static void Main()
    {
        string filePath = "your_excel_file.xlsx";
        using (SpreadsheetDocument spreadsheetDocument = SpreadsheetDocument.Open(filePath, false))
        {
            WorkbookPart workbookPart = spreadsheetDocument.WorkbookPart;
            WorksheetPart worksheetPart = workbookPart.WorksheetParts.FirstOrDefault();
            if (worksheetPart != null)
            {
                SheetData sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();
                foreach (Row row in sheetData.Elements<Row>())
                {
                    foreach (Cell cell in row.Elements<Cell>())
                    {
                        string cellValue = GetCellValue(workbookPart, cell);
                        Console.Write(cellValue + "\t");
                    }
                    Console.WriteLine();
                }
            }
        }
    }

    static string GetCellValue(WorkbookPart workbookPart, Cell cell)
    {
        string value = cell.CellValue?.InnerText;
        if (cell.DataType != null && cell.DataType.Value == CellValues.SharedString)
        {
            SharedStringTablePart stringTablePart = workbookPart.GetPartsOfType<SharedStringTablePart>().First();
            value = stringTablePart.SharedStringTable.ElementAt(int.Parse(value)).InnerText;
        }
        return value;
    }
}

demo2

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

string filePath = @"C:\test.xlsx"; // 替换为你的文件路径
var result = new List<string>();

using (var document = SpreadsheetDocument.Open(filePath, false))
{
    var workbookPart = document.WorkbookPart;
    var sheets = workbookPart.Workbook.Sheets;

    foreach (var sheet in sheets)
    {
        var worksheetPart = (WorksheetPart)workbookPart.GetPartById(sheet.Id);
        var sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();
        
        if (sheetData == null) continue; // 空工作表跳过

        // 遍历行(RowIndex 从 1 开始)
        foreach (var row in sheetData.Elements<Row>())
        {
            int rowNumber = row.RowIndex.Value;
            
            // 遍历单元格(Column 需通过 CellReference 解析,如 "A1")
            foreach (var cell in row.Elements<Cell>())
            {
                string cellText = GetCellText(cell);
                if (!string.IsNullOrEmpty(cellText))
                {
                    string column = GetColumnLetter(cell.CellReference.Value); // 辅助函数
                    result.Add($"Sheet: {sheet.Name}, 单元格: {column}{rowNumber}, 内容: {cellText}");
                }
            }
        }
    }
}

// 输出结果(控制台/文件)
foreach (var line in result)
{
    Console.WriteLine(line);
}


// 辅助函数 1:解析单元格内容(文本/公式)
string GetCellText(Cell cell)
{
    if (cell.InlineString != null) // 纯文本(非公式)
    {
        return cell.InlineString.Text?.Text?.Trim();
    }
    if (cell.CellValue != null) // 公式或数字(文本形式)
    {
        return cell.CellValue.Text?.Trim(); // 直接取公式字符串(如 "=SUM(A1:A10)")
    }
    return null;
}

// 辅助函数 2:CellReference 转列字母(如 "A1" → "A")
string GetColumnLetter(string cellReference)
{
    int endIndex = cellReference.IndexOfAny("0123456789".ToCharArray());
    return endIndex > 0 ? cellReference.Substring(0, endIndex) : "";
}

demo3

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;

/// 获取单元格信息  这也是官方获取值的方法
/// 参数一为单元格对象本身,参数二为WorkbookPart.SharedStringTablePart,它存储了所有以SharedStringTable方式存储数据的子元素。
static string GetValue(Cell cell, SharedStringTablePart stringTablePart)
{
    if (cell.ChildElements.Count == 0)
        return "";
    //get cell value
    String value = cell.CellValue!.InnerText;
    //Look up real value from shared string table
    if ((cell.DataType != null) && (cell.DataType == CellValues.SharedString))
        value = stringTablePart.SharedStringTable
            .ChildElements[Int32.Parse(value)]
            .InnerText;
    return value;
}

/// 获取Excel指定工作表数据
/// 参数一为Excel文件路径,参数二为工作表名称
void GetExcelVlaue(string filePath)
{
    //打开文件
    SpreadsheetDocument document = SpreadsheetDocument.Open(filePath, false);
    WorkbookPart? workbook = document.WorkbookPart;
    //返回第一个工作表
    IEnumerable<Sheet> sheets = document.WorkbookPart!.Workbook.Descendants<Sheet>();
    if (sheets.Count() != 0)
    {
        WorksheetPart worksheetPart = (WorksheetPart)document.WorkbookPart.GetPartById(sheets.First().Id!);
        Worksheet worksheet = worksheetPart.Worksheet;
        IEnumerable<Row> rows = worksheet.Descendants<Row>();
        foreach (Row row in rows)//获取行的值
        {
            foreach (Cell cell in row)
            {
                string columnValue = GetValue(cell, workbook!.SharedStringTablePart!);
                Console.Write(columnValue+" ");
            }
            Console.WriteLine();
        }
    }
}

GetExcelVlaue("字段替换表格.xlsx");

demo4完整代码

安装依赖

dotnet add package DocumentFormat.OpenXml
dotnet add package DocumentFormat.OpenXml.Vba  # 用于 ActiveX 控件解析
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
using DocumentFormat.OpenXml.Vba;
using System.Collections.Generic;
using System.Linq;

/// <summary>
/// Excelのコントロール(フォーム/ActiveX)からテキストを抽出するクラス
/// 対応範囲:ボタン、チェックボックス、ドロップダウン、グループボックス、アクティブXコントロール、コメント
/// </summary>
public class ExcelControlTextExtractor
{
    private readonly List<string> _results = new List<string>(); // 抽出結果格納

    /// <summary>
    /// コントロールのテキストを抽出するメインメソッド
    /// </summary>
    /// <param name="filePath">Excelファイルパス(.xlsx/.xlsm対応)</param>
    /// <returns>抽出結果リスト</returns>
    public List<string> ExtractControls(string filePath)
    {
        using (var document = SpreadsheetDocument.Open(filePath, false))
        {
            var workbookPart = document.WorkbookPart;
            
            // 1. フォームコントロール(Excel標準コントロール)の抽出
            ExtractFormControls(workbookPart);
            
            // 2. ActiveXコントロール(VBA対応コントロール)の抽出
            ExtractActiveXControls(workbookPart);
        }
        return _results;
    }

    #region ① フォームコントロール(Form Control)処理
    /// <summary>
    /// フォームコントロール(ボタン、チェックボックスなど)のテキストを抽出
    /// </summary>
    private void ExtractFormControls(WorkbookPart workbookPart)
    {
        foreach (var sheet in workbookPart.Workbook.Sheets)
        {
            var worksheetPart = (WorksheetPart)workbookPart.GetPartById(sheet.Id);
            var worksheet = worksheetPart.Worksheet;
            string sheetName = sheet.Name ?? "Sheet";

            // コントロールが存在する場合
            if (worksheet.Controls != null)
            {
                foreach (var control in worksheet.Controls.Controls)
                {
                    try
                    {
                        switch (control)
                        {
                            // ▶ ボタン(押下可能なコントロール)
                            case Button button:
                                _results.Add($"【フォームボタン】{sheetName}: {button.Text}");
                                ExtractControlComments(control, sheetName); // コメントの抽出
                                break;

                            // ▶ チェックボックス(複数選択可能)
                            case CheckBox checkBox:
                                _results.Add($"【チェックボックス】{sheetName}: {checkBox.Caption}(状態:{checkBox.Checked})");
                                break;

                            // ▶ ドロップダウンリスト(選択肢を表示)
                            case ComboBox comboBox:
                                string options = comboBox.List != null 
                                    ? comboBox.List // 直接記述された選択肢(例: "A,B,C")
                                    : $"参照セル: {comboBox.ListFillRange}"; // セル範囲参照
                                _results.Add($"【ドロップダウン】{sheetName}: {options}");
                                break;

                            // ▶ グループボックス(コントロールをグループ化)
                            case GroupBox groupBox:
                                _results.Add($"【グループボックス】{sheetName}(タイトル): {groupBox.Text}");
                                ExtractChildControls(groupBox, sheetName); // 子コントロールの再帰処理
                                break;

                            // ▶ リストボックス(一覧表示コントロール)
                            case ListBox listBox:
                                _results.Add($"【リストボックス】{sheetName}: 項目数={listBox.Rows}");
                                break;

                            // ▶ ラジオボタン(単一選択)
                            case OptionButton optionButton:
                                _results.Add($"【ラジオボタン】{sheetName}: {optionButton.Caption}(選択:{optionButton.Checked})");
                                break;

                            default:
                                _results.Add($"【未対応フォームコントロール】{sheetName}: {control.LocalName}");
                                break;
                        }
                    }
                    catch (System.Exception ex) { _results.Add($"エラー: {ex.Message}"); }
                }
            }
        }
    }

    /// <summary>
    /// グループボックス内の子コントロールを再帰的に抽出(漏れ防止対策)
    /// </summary>
    private void ExtractChildControls(GroupBox groupBox, string sheetName)
    {
        foreach (var childControl in groupBox.ChildControls) // 子コントロールのリスト
        {
            if (childControl is Control control)
            {
                // 子コントロールを再びSwitch文で処理(再帰)
                ExtractFormControls(new WorkbookPart { Workbook = new Workbook { 
                    Sheets = new Sheets { new Sheet { Name = sheetName } }
                } }, control, sheetName);
            }
        }
    }

    // コントロール用のオーバーロードメソッド(子コントロール専用)
    private void ExtractFormControls(WorkbookPart wbPart, Control control, string sheetName)
    {
        switch (control)
        {
            case Button btn: _results.Add($"  子ボタン: {btn.Text}"); break;
            case CheckBox chk: _results.Add($"  子チェック: {chk.Caption}"); break;
            // 他の子コントロールも同様に追加
        }
    }
    #endregion

    #region ② ActiveXコントロール(ActiveX Control)処理
    /// <summary>
    /// ActiveXコントロール(VBA関連コントロール)のテキストを抽出
    /// </summary>
    private void ExtractActiveXControls(WorkbookPart workbookPart)
    {
        foreach (var olePart in workbookPart.GetPartsOfType<OleObjectPart>())
        {
            var oleObject = olePart.OleObject;
            if (oleObject == null) continue;

            string controlType = oleObject.ProgId?.Value;
            var vbaControl = olePart.GetVbaControl(); // VBAコントロールの取得
            string sheetName = GetSheetName(workbookPart, olePart);

            try
            {
                if (vbaControl == null) return;

                switch (controlType)
                {
                    // ▶ ActiveXボタン(通常のボタン)
                    case "Forms.CommandButton.1":
                        string caption = vbaControl.GetProp("Caption"); // 表示テキスト
                        _results.Add($"【ActiveXボタン】{sheetName}: {caption}");
                        ExtractActiveXComments(olePart, sheetName); // ActiveX用コメント抽出
                        break;

                    // ▶ テキストボックス(文字列を入力可能)
                    case "Forms.TextBox.1":
                        string text = vbaControl.GetProp("Text"); // 入力内容
                        _results.Add($"【テキストボックス】{sheetName}: {text}");
                        break;

                    // ▶ ドロップダウン(ActiveX版)
                    case "Forms.ComboBox.1":
                        string items = vbaControl.GetProp("List"); // 選択肢(カンマ区切り)
                        _results.Add($"【ActiveXドロップダウン】{sheetName}: 選択肢={items}");
                        break;

                    // ▶ チェックボックス(ActiveX版)
                    case "Forms.CheckBox.1":
                        string state = vbaControl.GetProp("Value"); // 0=未選択, 1=選択
                        string label = vbaControl.GetProp("Caption");
                        _results.Add($"【ActiveXチェック】{sheetName}: {label}(状態:{state})");
                        break;

                    // ▶ ラベル(テキスト表示のみ)
                    case "Forms.Label.1":
                        _results.Add($"【ラベル】{sheetName}: {vbaControl.GetProp("Caption")}");
                        break;

                    default:
                        _results.Add($"【未対応ActiveX】{sheetName}: {controlType}");
                        break;
                }
            }
            catch { /* エラーハンドリング */ }
        }
    }

    /// <summary>
    /// ActiveXコントロールのコメントを抽出(Excel 2013以降対応)
    /// </summary>
    private void ExtractActiveXComments(OleObjectPart olePart, string sheetName)
    {
        var drawingPart = olePart.GetParentPartsOfType<DrawingPart>().FirstOrDefault();
        if (drawingPart == null) return;

        var commentList = drawingPart.Drawing.Descendants<CommentList>().FirstOrDefault();
        if (commentList != null)
        {
            foreach (var comment in commentList.Elements<Comment>())
            {
                _results.Add($"  コメント: {comment.Text?.Text}(ActiveX用)");
            }
        }
    }
    #endregion

    #region ③ 共通ユーティリティメソッド
    /// <summary>
    /// コントロールに関連付けられたコメントを抽出(右クリック→「コメントの挿入」)
    /// </summary>
    private void ExtractControlComments(OpenXmlElement control, string sheetName)
    {
        var commentList = control.Ancestors<CommentList>().FirstOrDefault();
        if (commentList == null) return;

        foreach (var comment in commentList.Elements<Comment>())
        {
            _results.Add($"  コメント: {comment.Text?.Text}(フォーム用)");
        }
    }

    /// <summary>
    /// コントロールが属するワークシート名を取得
    /// </summary>
    private string GetSheetName(WorkbookPart workbookPart, OpenXmlPart part)
    {
        var relationship = workbookPart.GetIdOfPart(part);
        return workbookPart.Workbook.Sheets
            .Where(s => s.Id == relationship)
            .Select(s => s.Name)
            .FirstOrDefault() ?? "不明";
    }

    /// <summary>
    /// VBAコントロールのプロパティを簡易取得(拡張メソッド)
    /// </summary>
    public static string GetProp(this VbaControl control, string propName)
    {
        return control.Properties?.Elements<VbaProperty>()
            .Where(p => p.Name == propName)
            .Select(p => p.StringValue)
            .FirstOrDefault()?.Trim() ?? "未設定";
    }
    #endregion

    // テスト用メインメソッド
    public static void Main()
    {
        var extractor = new ExcelControlTextExtractor();
        var results = extractor.ExtractControls(@"C:\test.xlsm"); // テストファイルパス

        System.IO.File.WriteAllLines(@"C:\result.txt", results); // 結果をファイル出力
        foreach (var line in results) Console.WriteLine(line); // コンソール表示
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值