Delo z Excelom v ogrodju .NET neodvisno od nameščene različice Excela
Delovno okolje
- Visual Studio
-
- Visual Studio 2022
- .MREŽA
-
- .NET 6.0
- Windows
-
- Windows 7
- Windows 11
- Excel
-
- Microsoft 365
- Office 2007
Predpogoji
- Windows
-
- Ena od različic
- Excel
-
- Ena od različic
Težave s knjižnicami, ki delujejo z Excelom
Eden od načinov za programsko interakcijo z Excelom je Microsoft.Office.Interop.Excel
sklicevanje .
To je podobno delu neposredno z aplikacijo Excel prek COM, zato se nekoliko razlikuje od dela s podatki v datoteki Excel.
Kot prostor mora biti Excel nameščen v okolju, ki ga je treba izvesti, vendar so številne funkcije Excela na voljo na programski strani.
Microsoft.Office.Interop.Excel
Če uporabljate program, boste mislili, da bo program napisan na naslednji način.
// 実行プログラムの場所にある Excel ファイル
var excelFilePath = $@"{Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName)}\Sample.xlsx";
// Excel のオブジェクトは参照したら必ず解放する必要があります。
// 解放しないと Excel のプロセスが残り続けます。
Microsoft.Office.Interop.Excel.Application? excel = null;
Microsoft.Office.Interop.Excel.Workbooks? books = null;
Microsoft.Office.Interop.Excel.Workbook? book = null;
Microsoft.Office.Interop.Excel.Sheets? sheets = null;
Microsoft.Office.Interop.Excel.Worksheet? sheet = null;
Microsoft.Office.Interop.Excel.Range? cells = null;
Microsoft.Office.Interop.Excel.Range? range1 = null;
Microsoft.Office.Interop.Excel.Range? range2 = null;
try
{
// Excel アプリケーションを生成(起動)します
excel = new Microsoft.Office.Interop.Excel.Application
{
DisplayAlerts = false
};
// ワークブック一覧を参照します。参照する場合は必ず変数に保持します
books = excel.Workbooks;
// Excel ファイルを開きます
book = books.Open(excelFilePath);
// シート一覧を参照するので変数に保持します
sheets = book.Worksheets;
// シートを参照します。最初のシートは 1 になります
sheet = (Microsoft.Office.Interop.Excel.Worksheet)sheets[1];
// セル一覧を参照します
cells = sheet.Cells;
// 左上のセルを参照します。一番左上は [1, 1] になります
range1 = (Microsoft.Office.Interop.Excel.Range)cells[1, 1];
// セルの値を取得します。値の取得なので後で解放する必要はありません
var value = (int)range1.Value;
// 下のセルを参照します
range2 = (Microsoft.Office.Interop.Excel.Range)cells[2, 1];
// 日付分足してセットします
range2.Value = DateTime.Now.Day + value;
// 保存して閉じます
book.Close(SaveChanges: true);
Console.WriteLine("処理が完了しました。");
}
catch (Exception ex)
{
// 閉じていなければ保存せずに閉じます
// 開きっぱなしだと Excel 起動時に保存されていないデータとして表示される場合があります
if (book != null) book.Close(SaveChanges: false);
Console.WriteLine("処理が失敗しました。");
Console.WriteLine(ex);
}
finally
{
// 終了していなければ終了します
if (excel != null) excel.Quit();
// 例外が発生した場合でも必ずリソースを解放するようにします
if (range1 != null) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(range1);
if (range2 != null) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(range2);
if (cells != null) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(cells);
if (sheet != null) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(sheet);
if (sheets != null) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(sheets);
if (book != null) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(book);
if (books != null) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(books);
if (excel != null) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(excel);
}
Težko je vsakič sprostiti vire, a ker lahko pripravljene razrede uporabite, lahko obdelavo Excela izvedete relativno intuitivno.
Pomanjkljivost pa je, da se mora različica knjižnice, na katero se sklicuje program, ujemati ali biti združljiva z različico Excela, nameščeno v okolju, v katerem se izvaja. Program, ustvarjen s sklicevanjem na knjižnico programa Excel notranje različice 15.0 (2013), se lahko na primer zažene le, ko je nameščen Excel 2013. Če želite, da se program izvaja v številnih okoljih, boste morda morali ohraniti Excelovo namestitev v dosledni različici.
Če je takšna operacija mogoča, je v redu, če pa je nameščena različica Excela drugačna, je ni mogoče sprejeti. Zato je treba nekaj storiti na programski strani.
Dinamično sklicevanje na knjižnice z dinamičnim sklicevanjem, namesto da bi se nanje neposredno sklicevali
Do težave v tem primeru pride, ker je sklic na različico knjižnice nespremenljiv, ko je program ustvarjen. To pomeni, da je namesto določanja različice v času ustvarjanja programa potrebno določiti različico v času izvajanja programa.
Obstaja več načinov za to, vendar ga bomo tokrat rešili z uporabo "" "" in "Type.GetTypeFromProgID
Activator.CreateInstance
".dynamic
Običajno je v C # treba določiti informacije o vrsti v času ustvarjanja programa, če pa je dynamic
vrsta , se lahko tip določi v času izvedbe.
object
Če je primerek, nastavljen na spremenljivko, za razliko od dynamic
vrst razred, lahko pokličete tudi metode in lastnosti tega razreda.
Ker pa se tisto, kar gre v spremenljivko, določi v času izvršitve, se bo v času izvršitve pojavila napaka, če ni določene metode.
Koda, ustvarjena z njimi, je naslednja.
// 実行プログラムの場所にある Excel ファイル
var excelFilePath = $@"{Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName)}\Sample.xlsx";
// Excel のオブジェクトは参照したら必ず解放する必要があります。
// 解放しないと Excel のプロセスが残り続けます。
dynamic? excel = null;
dynamic? books = null;
dynamic? book = null;
dynamic? sheets = null;
dynamic? sheet = null;
dynamic? cells = null;
dynamic? range1 = null;
dynamic? range2 = null;
try
{
// Excel.Application の Type を取得
var type = Type.GetTypeFromProgID("Excel.Application");
if (type == null)
{
Console.WriteLine("Excel がインストールされていません。");
return;
}
// Excel アプリケーションを生成(起動)します
excel = Activator.CreateInstance(type);
if (excel == null)
{
Console.WriteLine("Excel.Application のインスタンスの生成に失敗しました。");
return;
}
excel.DisplayAlerts = false;
// ワークブック一覧を参照します。参照する場合は必ず変数に保持します
books = excel.Workbooks;
// Excel ファイルを開きます
book = books.Open(excelFilePath);
// シート一覧を参照するので変数に保持します
sheets = book.Worksheets;
// シートを参照します。最初のシートは 1 になります
sheet = (Microsoft.Office.Interop.Excel.Worksheet)sheets[1];
// セル一覧を参照します
cells = sheet.Cells;
// 左上のセルを参照します。一番左上は [1, 1] になります
range1 = (Microsoft.Office.Interop.Excel.Range)cells[1, 1];
// セルの値を取得します。値の取得なので後で解放する必要はありません
var value = (int)range1.Value;
// 下のセルを参照します
range2 = (Microsoft.Office.Interop.Excel.Range)cells[2, 1];
// 日付分足してセットします
range2.Value = DateTime.Now.Day + value;
// 保存して閉じます
book.Close(SaveChanges: true);
Console.WriteLine("処理が完了しました。");
}
catch (Exception ex)
{
// 閉じていなければ保存せずに閉じます
// 開きっぱなしだと Excel 起動時に保存されていないデータとして表示される場合があります
if (book != null) book.Close(SaveChanges: false);
Console.WriteLine("処理が失敗しました。");
Console.WriteLine(ex);
}
finally
{
// 終了していなければ終了します
if (excel != null) excel.Quit();
// 例外が発生した場合でも必ずリソースを解放するようにします
if (range1 != null) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(range1);
if (range2 != null) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(range2);
if (cells != null) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(cells);
if (sheet != null) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(sheet);
if (sheets != null) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(sheets);
if (book != null) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(book);
if (books != null) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(books);
if (excel != null) System.Runtime.InteropServices.Marshal.FinalReleaseComObject(excel);
}
Vrsta deklaracije spremenljivke je , ustvarjanje pa je dynamic
nekoliko drugačno, Excel.Application
preostanek kode pa se skoraj ponovno uporabi.
Ker se zgornja koda ne nanaša na Excelovo knjižnico, ni mogoče uporabiti ciljnih informacij o razredu, povezanih z Excelom. Zato je vrsta spremenljivke vse dynamic
.
Ker se ne moremo neposredno sklicevati na razred, namesto tega Excel.Application
Type.GetTypeFromProgID
dobimo podatke Activator.CreateInstance
o vrsti in jih posredujemo,Excel.Application
da ustvarimo Excel.Application
primerek .
Mimogrede, v okolju, kjer Excel ni nameščen, ga ne morete dobiti v Type
, zato je mogoče izolirati, Type.GetTypeFromProgID
ali je nameščen ali ne.
dynamic
Pomanjkljivost uporabe je, da razreda ni mogoče določiti pri gradnji programa.
Intellisense, ki je funkcija dokončanja pri vnosu kode, ne prikazuje imen metod in imen lastnosti.
Morda je manj okorno napisati kodo s sklicevanjem na knjižnico na začetku in jo zamenjati s dynamic
kasneje.
Ko se izvaja v okolju Microsoft 365, lahko potrdite, da se odraža na naslednji način.
V nadaljevanju je prikazan zagon v veliko starejši različici sistema Office 2007. Če ne uporabljate funkcije, ki deluje samo v določeni različici, lahko poskrbite, da deluje precej široko.
Mimogrede, če ga zaženete v okolju, kjer Excel ni nameščen, lahko pravilno ugotovite, da ga ni mogoče obdelati.