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;
}
}
ツッコミ仙人
長っ! 心折れるわ
コメント