[OpenXml]xlsxファイル読み出し&別名保存[C#]

OpenXML

OpenXmlは読み出すだけでタイヘン。正直、ClosedXmlとかNPOIとか使う方がラクなのよ。

ツッコミ仙人
ツッコミ仙人

じゃが、どうしてもOpenXmlを使わねばならぬ場面が来たら、腹くくって使うしか無いわい

さて、OpenXmlは通常のセーブ処理で別名保存が出来ないっぽいので(なんでだ)、別名保存したい場合は、MemoryStreamを使って読むしかないっぽい。
※ちなみにVisualStudio 2022を使う想定です。

とりあえずOpenXmlを使えるようにするので、vs2022のツールバーから、
 ツール(T)>NuGet パッケージ マネージャー(N)>ソリューションの NuGet パッケージの管理(N)
パッケージ管理の画面の「参照」タブで、[OpenXML]と打って検索。「DocumentFormat.OpenXml」を選んでインストールしてください。

んじゃ、サンプル。

サンプル(呼び出し側)

//例えばボタンを押されたとき
private void button1_Click(object sender, EventArgs e)
{
    //xlsxファイルを読み出す(ExcelWorkクラスは下で説明)
    var xlsx = ExcelWork.Open(@"C:\work\sample.xlsx");

    //操作するシートを選択
    xlsx.SelectSheet("Sheet1");

    //セルに記載
    xlsx.SetValue("A", 1, "test");

    //別名保存
    xlsx.SaveAs(@"c:\work\new_sample.xlsx");
    Debug.WriteLine("★終了");
}

xlsx処理クラスのサンプル

※実際使う時はエラー処理とか例外処理とか追加してください。

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

class ExcelWork
{
    private ExcelWork() { }
    public void Dispose() => _document?.Dispose();

    //Excel操作用(多いなぁ)
    private SpreadsheetDocument _document;
    private WorkbookPart _workbookPart;
    private WorksheetPart _worksheetPart;
    private Sheets _sheets;
    private SheetData _sheetData;

    //ファイル読み書き用
    private MemoryStream _memoryStream;

    //エクセルファイルを開くよ
    public static ExcelWork Open(string xlsxFileName)
    {
        var obj = new ExcelWork();

        //別名でセーブする場合はMemoryStreamで読み出し
        obj._memoryStream = new MemoryStream();
        byte[] bytes = File.ReadAllBytes(xlsxFileName);
        obj._memoryStream.Write(bytes, 0, bytes.Length);

        obj._document = SpreadsheetDocument.Open(obj._memoryStream,
                         true, new OpenSettings { AutoSave = false, });
        obj._workbookPart = obj._document.WorkbookPart;

        obj._sheets = obj._workbookPart.Workbook.GetFirstChild<Sheets>();

        return obj;
    }

    //名前を付けて保存
    public void SaveAs(string fileFullpath)
    {
        Worksheet worksheet = _worksheetPart.Worksheet;
        worksheet.Save();
        _document.Close();

        File.WriteAllBytes(fileFullpath, _memoryStream.ToArray());
    }

    //シートを選択
    public void SelectSheet(string sheetName)
    {
        // workbookから指定したシートを見つける
        var theSheet = _workbookPart.Workbook.Descendants<Sheet>().
            Where(s => s.Name == sheetName).FirstOrDefault();

        //  WorkSheetPartを取り出す
        _worksheetPart = (WorksheetPart)_workbookPart.GetPartById(theSheet.Id);

        // SheetDataを見つける
        var worksheet = _worksheetPart.Worksheet;
        _sheetData = worksheet.GetFirstChild<SheetData>();
    }

    //セルに文字列を記載。
    public void SetValue(string columnName, uint rowIndex, string text)
    {
        Cell cell = CreateCell(columnName, rowIndex);
        cell.CellValue = new CellValue(text);
        cell.DataType = new EnumValue<CellValues>(CellValues.String);
    }

    // セルを作成。存在していたらそのセルを返す
    public Cell CreateCell(string columnName, uint rowIndex)
    {
        // SheetDataを見つける
        var worksheet = _worksheetPart.Worksheet;
        var sheetData = worksheet.GetFirstChild<SheetData>();

        // 行を見つける
        var row = sheetData.Elements<Row>().FirstOrDefault(r => r.RowIndex == rowIndex);
        if (row == null)
        {
            //  行がなければ追加する
            row = new Row { RowIndex = rowIndex };
            sheetData.Append(row);
        }

        // その行の指定したカラムのセルを取り出す
        var cellReference = columnName + rowIndex;
        var cell = row.Elements<Cell>().FirstOrDefault(c => c.CellReference.Value == cellReference);
        if (cell != null)
            return cell;
            
        // セルがなければセルを追加する 
        var refCell = row.Elements<Cell>()
            .FirstOrDefault(c => string.Compare(c.CellReference.Value, cellReference, true) > 0);
            
        var newCell = new Cell()
        {
            CellReference = cellReference
        };
        row.InsertBefore(newCell, refCell);
        return newCell;
    }
}
ツッコミ仙人
ツッコミ仙人

長っ! 心折れるわ

ダウンロード

ここからどうぞ

コメント

タイトルとURLをコピーしました