العمل مع Excel في .NET بشكل مستقل عن الإصدار المثبت من Excel

تحديث الصفحة :
تاريخ إنشاء الصفحة :

بيئة التشغيل

فيجوال ستوديو
  • فيجوال ستوديو 2022
.صافي
  • .NET 6.0
نوافذ
  • ويندوز 7
  • ويندوز ١١
اكسل
  • مايكروسوفت 365
  • أوفيس 2007

المتطلبات المسبقه

نوافذ
  • أحد الإصدارات
اكسل
  • أحد الإصدارات

مشاكل مع المكتبات التي تعمل مع Excel

تتمثل إحدى طرق التفاعل برمجيا مع Excel Microsoft.Office.Interop.Excel في الرجوع إلى . هذا مشابه للعمل مباشرة مع تطبيق Excel عبر COM ، لذلك يختلف قليلا عن العمل مع البيانات في ملف Excel. كفرضية ، يجب تثبيت Excel في البيئة المراد تنفيذها ، ولكن تتوفر العديد من وظائف Excel من جانب البرنامج.

Microsoft.Office.Interop.Excel إذا كنت تستخدم البرنامج ، فستعتقد أنه سيتم كتابة البرنامج بالطريقة التالية.

// 実行プログラムの場所にある 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);
}

من المزعج أن تضطر إلى تحرير الموارد في كل مرة ، ولكن نظرا لأنه يمكنك استخدام الفئات المعدة ، يمكنك إجراء معالجة Excel بشكل حدسي نسبيا.

ومع ذلك ، فإن العيب هو أن إصدار المكتبة المشار إليه بواسطة البرنامج يجب أن يتطابق أو يكون متوافقا مع إصدار Excel المثبت في البيئة التي يعمل فيها. على سبيل المثال، يمكن تشغيل برنامج تم إنشاؤه بالرجوع إلى مكتبة الإصدار 15.0 (2013) الداخلية من Excel فقط عند تثبيت Excel 2013. إذا كنت تريد تشغيل البرنامج في العديد من البيئات، فقد تحتاج إلى الاحتفاظ بتثبيت Excel قيد التشغيل على إصدار متسق.

إذا كانت هذه العملية ممكنة ، فلا بأس بذلك ، ولكن إذا كان الإصدار المثبت من Excel مختلفا ، فلا يمكن استيعابه. لذلك ، من الضروري القيام بشيء ما على جانب البرنامج.

الرجوع إلى المكتبات ديناميكيا باستخدام الديناميكية بدلا من الرجوع إليها مباشرة

تحدث المشكلة في هذه الحالة لأنه يتم الرجوع إلى إصدار المكتبة ثابت عند إنشاء البرنامج. هذا يعني أنه بدلا من تحديد الإصدار في وقت إنشاء البرنامج ، من الضروري تحديد الإصدار في وقت تنفيذ البرنامج.

هناك عدة طرق للقيام بذلك ، ولكن هذه المرة سنحلها باستخدام "" "" و "Type.GetTypeFromProgIDActivator.CreateInstance".dynamic

عادة ، في C # ، من الضروري تحديد معلومات النوع في وقت إنشاء البرنامج ، ولكن إذا كان dynamic النوع ، يمكن تحديد النوع في وقت التنفيذ. object على عكس dynamic الأنواع ، إذا كان المثيل المعين إلى متغير هو فئة ، فيمكنك أيضا استدعاء طرق وخصائص تلك الفئة. ومع ذلك ، نظرا لأن ما يدخل في المتغير يتم تحديده في توقيت التنفيذ ، فسيحدث خطأ في وقت التنفيذ إذا لم تكن هناك طريقة محددة.

التعليمات البرمجية التي تم إنشاؤها باستخدام هذه هي كما يلي.

// 実行プログラムの場所にある 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);
}

نوع إعلان المتغير هو dynamic ، وإنشاء Excel.Application يختلف قليلا ، ولكن يتم إعادة استخدام بقية الكود تقريبا.

نظرا لأن التعليمة البرمجية أعلاه لا تشير إلى مكتبة Excel ، فلا يمكن استخدام معلومات الفئة المتعلقة ب Excel المستهدفة. لذلك ، فإن نوع المتغير هو كل dynamic . أيضا ، نظرا لأنه لا يمكننا الرجوع إلى الفصل مباشرة ،Excel.Application فإننا بدلا من ذلك Excel.Application Type.GetTypeFromProgID نحصل على معلومات Activator.CreateInstance النوع ونمررها إلى لإنشاء Excel.Application مثيل ل . بالمناسبة ، في بيئة لم يتم فيها تثبيت Excel ، لا يمكنك الحصول عليه Type ، Type.GetTypeFromProgID لذلك من الممكن عزل ما إذا كان مثبتا أم لا.

dynamic عيب الاستخدام هو أنه لا يمكن تحديد الفئة عند إنشاء البرنامج. لا يعرض Intellisense ، وهي وظيفة إكمال عند إدخال التعليمات البرمجية ، أسماء الأساليب وأسماء الخصائص. قد يكون أقل تعقيدا لكتابة التعليمات البرمجية مع الإشارة إلى المكتبة في البداية واستبدالها في dynamic وقت لاحق.

عند التشغيل في بيئة Microsoft 365، يمكنك التأكد من أنه ينعكس على النحو التالي.

التالي هو نتيجة تشغيله على إصدار أقدم بكثير من Office 2007. إذا كنت لا تستخدم وظيفة تعمل فقط في إصدار معين ، فيمكنك جعلها تعمل على نطاق واسع.

بالمناسبة ، إذا قمت بتشغيله في بيئة لم يتم تثبيت Excel فيها ، فيمكنك تحديد أنه لا يمكن معالجته بشكل صحيح.