ایکسل کے انسٹال شدہ ورژن سے آزادانہ طور پر .NET میں ایکسل کے ساتھ کام کریں

جب صفحے کی تازہ کاری :
صفحہ تخلیق تاریخ :

آپریٹنگ ماحول

Visual Studio
  • Visual Studio 2022
.جال
  • .NET 6.0
Windows
  • ونڈوز 7
  • ونڈوز 11
Excel
  • Microsoft 365
  • Office 2007

ضروری شرائط

Windows
  • ورژن میں سے ایک
Excel
  • ورژن میں سے ایک

ایکسل کے ساتھ کام کرنے والی لائبریریوں کے ساتھ مسائل

ایکسل کے ساتھ پروگرامی طور پر بات چیت کرنے کا ایک طریقہ حوالہ دینا ہے Microsoft.Office.Interop.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);
}

ہر بار وسائل کو جاری کرنا مشکل ہے ، لیکن چونکہ آپ تیار کردہ کلاسوں کا استعمال کرسکتے ہیں ، لہذا آپ ایکسل پروسیسنگ کو نسبتا فطری طور پر انجام دے سکتے ہیں۔

تاہم ، خرابی یہ ہے کہ پروگرام کے ذریعہ حوالہ کردہ لائبریری کا ورژن اس ماحول میں انسٹال ایکسل کے ورژن سے میل کھاتا یا مطابقت رکھتا ہے جس میں یہ چل رہا ہے۔ مثال کے طور پر ، ایکسل کے اندرونی ورژن 15.0 (2013) لائبریری کا حوالہ دے کر بنایا گیا پروگرام صرف اسی وقت چل سکتا ہے جب ایکسل 2013 انسٹال ہو۔ اگر آپ چاہتے ہیں کہ آپ کا پروگرام بہت سے ماحول میں چلے تو ، آپ کو اپنی ایکسل انسٹالیشن کو مستقل ورژن پر چلانے کی ضرورت ہوسکتی ہے۔

اگر اس طرح کا آپریشن ممکن ہے تو ، یہ ٹھیک ہے ، لیکن اگر ایکسل کا انسٹال ورژن مختلف ہے تو ، اسے ایڈجسٹ نہیں کیا جاسکتا ہے۔ لہذا ، پروگرام کی طرف سے کچھ کرنا ضروری ہے۔

لائبریریوں کو براہ راست حوالہ دینے کے بجائے متحرک طور پر متحرک طریقے سے حوالہ دینا

اس معاملے میں مسئلہ اس لئے ہوتا ہے کیونکہ پروگرام بناتے وقت لائبریری ورژن کا حوالہ دیا جاتا ہے۔ اس کا مطلب یہ ہے کہ پروگرام کی تخلیق کے وقت ورژن کا تعین کرنے کے بجائے ، پروگرام کے نفاذ کے وقت ورژن کا تعین کرنا ضروری ہے۔

ایسا کرنے کے کئی طریقے ہیں ، لیکن اس بار ہم اسے "" "" اورType.GetTypeFromProgIDActivator.CreateInstance "" کا استعمال کرتے ہوئے حل کریں گے۔dynamic

عام طور پر ، سی # میں ، پروگرام کی تخلیق کے وقت قسم کی معلومات کا تعین کرنا ضروری ہے ، لیکن اگر قسم ہے تو ، عملدرآمد کے وقت قسم کا تعین کیا جاسکتا ہے 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 اس کی تخلیق قدرے مختلف ہے ، لیکن باقی کوڈ تقریبا دوبارہ استعمال کیا جاتا ہے۔

چونکہ مندرجہ بالا کوڈ ایکسل لائبریری کا حوالہ نہیں دیتا ہے ، لہذا ہدف ایکسل سے متعلق کلاس کی معلومات کا استعمال کرنا ممکن نہیں ہے۔ لہذا، متغیر کی قسم سب dynamic ہے. اس کے علاوہ ، چونکہ ہم کلاس کا براہ راست حوالہ نہیں دے سکتے ہیں ،Excel.Application لہذا ہم اس کے بجائے Type.GetTypeFromProgID Excel.Application ٹائپ کی معلومات Activator.CreateInstance حاصل کرتے ہیں اور اس کی مثال بنانے Excel.Application کے لئے اسے پاس کرتے ہیں۔ ویسے ، ایک ایسے ماحول میں جہاں ایکسل انسٹال نہیں ہے ، Type.GetTypeFromProgID آپ اسے اندر نہیں لا سکتے Type ہیں ، لہذا یہ الگ کرنا ممکن ہے کہ آیا یہ انسٹال ہے یا نہیں۔

dynamic استعمال کرنے کا نقصان یہ ہے کہ پروگرام کی تعمیر کرتے وقت کلاس کا تعین نہیں کیا جاسکتا ہے۔ انٹیلیسینس ، جو کوڈ داخل کرتے وقت تکمیل کا فنکشن ہے ، طریقہ کار کے نام اور جائیداد کے نام ظاہر نہیں کرتا ہے۔ شروع میں لائبریری کے حوالے سے کوڈ لکھنا اور اسے بعد میں تبدیل کرنا کم مشکل ہوسکتا ہے dynamic ۔

مائیکروسافٹ 365 ماحول میں چلتے وقت ، آپ اس بات کی تصدیق کرسکتے ہیں کہ یہ مندرجہ ذیل طور پر ظاہر ہوتا ہے۔

ذیل میں اسے آفس 2007 کے بہت پرانے ورژن پر چلانے کا نتیجہ ہے۔ اگر آپ ایسا فنکشن استعمال نہیں کرتے ہیں جو صرف ایک مخصوص ورژن میں کام کرتا ہے تو ، آپ اسے کافی وسیع پیمانے پر کام کرسکتے ہیں۔

ویسے ، اگر آپ اسے ایسے ماحول میں چلاتے ہیں جہاں ایکسل انسٹال نہیں ہے تو ، آپ صحیح طور پر اس بات کا تعین کرسکتے ہیں کہ اس پر عمل نہیں کیا جاسکتا ہے۔