Excel के स्थापित संस्करण से स्वतंत्र रूप से .NET में Excel के साथ कार्य करना

पेज अद्यतन :
पेज निर्माण की तारीख :

ऑपरेटिंग वातावरण

विजुअल स्टूडियो
  • विजुअल स्टूडियो 2022
।जाल
  • .नेट 6.0
विंडोज़
  • विंडोज 7
  • विंडोज 11
श्रेष्ठ होना
  • माइक्रोसॉफ्ट 365
  • ऑफिस 2007

आवश्यकताएँ

विंडोज़
  • संस्करणों में से एक
श्रेष्ठ होना
  • संस्करणों में से एक

Excel के साथ कार्य करने वाली लाइब्रेरीज़ की समस्याएँ

एक्सेल के साथ प्रोग्रामेटिक रूप से बातचीत करने का एक तरीका संदर्भ Microsoft.Office.Interop.Excel है। यह COM के माध्यम से 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 2013 स्थापित होने पर ही चल सकता है. यदि आप चाहते हैं कि आपका प्रोग्राम कई परिवेशों में चले, तो आपको अपनी Excel स्थापना को संगत संस्करण पर चलाने की आवश्यकता हो सकती है.

यदि ऐसा ऑपरेशन संभव है, तो यह ठीक है, लेकिन यदि एक्सेल का स्थापित संस्करण अलग है, तो इसे समायोजित नहीं किया जा सकता है। इसलिए, कार्यक्रम पक्ष पर कुछ करना आवश्यक है।

पुस्तकालयों को सीधे संदर्भित करने के बजाय गतिशील रूप से गतिशील रूप से संदर्भित करना

इस मामले में समस्या इसलिए होती है क्योंकि लायब्रेरी संस्करण संदर्भित निश्चित किया गया है जब प्रोग्राम बनाया गया है। इसका मतलब यह है कि कार्यक्रम निर्माण के समय संस्करण का निर्धारण करने के बजाय, कार्यक्रम निष्पादन के समय संस्करण का निर्धारण करना आवश्यक है।

इसे करने के कई तरीके हैं, लेकिन इस बार हम इसे "" "" और ""Type.GetTypeFromProgIDActivator.CreateInstance का उपयोग करके हल करेंगे।dynamic

आम तौर पर, सी # में, प्रोग्राम निर्माण के समय प्रकार की जानकारी निर्धारित करना आवश्यक है, लेकिन यदि प्रकार है, तो निष्पादन के समय प्रकार निर्धारित किया जा सकता है dynamicobject प्रकारों के विपरीत 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);
}

चर की घोषणा का प्रकार है, और Excel.Application का निर्माण थोड़ा अलग है, लेकिन बाकी कोड लगभग पुन: उपयोग किया जाता है dynamic

चूंकि उपरोक्त कोड एक्सेल लाइब्रेरी को संदर्भित नहीं करता है, इसलिए लक्ष्य एक्सेल से संबंधित क्लास जानकारी का उपयोग करना संभव नहीं है। इसलिए, चर का प्रकार सभी dynamic है। इसके अलावा, चूंकि हम सीधे क्लास को संदर्भित नहीं कर सकते हैं,Excel.Application इसलिए हम इसके बजाय Excel.Application Type.GetTypeFromProgID टाइप जानकारी Activator.CreateInstance प्राप्त करते हैं और इसे Excel.Application . वैसे, ऐसे वातावरण में जहां एक्सेल स्थापित नहीं है, आप इसे Type प्राप्त नहीं कर सकते हैं , Type.GetTypeFromProgID इसलिए यह अलग करना संभव है कि यह स्थापित है या नहीं।

dynamic उपयोग करने का नुकसान यह है कि प्रोग्राम का निर्माण करते समय कक्षा निर्धारित नहीं की जा सकती है। Intellisense, जो कोड दर्ज करते समय एक पूर्णता फ़ंक्शन है, विधि नाम और संपत्ति के नाम प्रदर्शित नहीं करता है। शुरुआत में पुस्तकालय के संदर्भ में कोड लिखना और इसे dynamic बाद में बदलना कम बोझिल हो सकता है।

Microsoft 365 वातावरण में चलते समय, आप पुष्टि कर सकते हैं कि यह निम्नानुसार दिखाई देता है।

इसे Office 2007 के बहुत पुराने संस्करण पर चलाने का परिणाम निम्न है. यदि आप किसी ऐसे फ़ंक्शन का उपयोग नहीं करते हैं जो केवल एक विशिष्ट संस्करण में काम करता है, तो आप इसे काफी व्यापक रूप से काम कर सकते हैं।

वैसे, यदि आप इसे ऐसे वातावरण में चलाते हैं जहां एक्सेल स्थापित नहीं है, तो आप सही ढंग से निर्धारित कर सकते हैं कि इसे संसाधित नहीं किया जा सकता है।