لماذا أحصل على خطأ في الذاكرة القيام ASP .NET Excel Interop؟

StackOverflow https://stackoverflow.com/questions/1662982

سؤال

هذه كنت العمل.. ونقلت رمز التخلص إلى كتلة أخيرا، والآن فشل في كل مرة.

لدي جدول بيانات اختبار مع 4 سجلات، 6 أعمدة طويلة. هنا هو الرمز الذي أستخدمه لإحضاره. هذا هو ASP .NET 3.5 على IIS 5 (جهاز الكمبيوتر الخاص بي) وعلى IIS 6 (خادم الويب).

إنه ينفث على الخط مباشرة قبل الصيد: "القيم = (كائن [،]) Range.Value2؛" مع الخطأ التالي:

11/2/2009 8:47:43 AM :: Not enough storage is available to complete this operation. (Exception from HRESULT: 0x8007000E (E_OUTOFMEMORY))

أيه أفكار؟ اقتراحات؟ حصلت على معظم الكود خارج CodeProject، لذلك ليس لدي أي فكرة عما إذا كانت هذه هي الطريقة الصحيحة للعمل مع Excel. شكرا لأي مساعدة يمكن أن تقدمها.

هنا هو رمزي:

Excel.ApplicationClass التطبيق = NULL؛ Excel.book Book = NULL؛ ورقة Excel.WorkSheet = NULL؛ Excel.Range نطاق = NULL؛ كائن [،] القيم = null؛ جرب {// تكوين تطبيق Excel = New Excel.ApplicationClass ()؛ app.visible = خطأ؛ app.screenupdating = خطأ؛ app.displayalerts = خطأ؛ / / افتح مثيل جديد من Excel مع دفتر الملفات التي تم تحميلها = app.bookbooks.open (المسار)؛ // الحصول على أول ورقة العمل في ورقة الكتاب = (Excel.worksheet) book.worksheets [1]؛ // البدء مع الخلية الأولى على نطاق الصف الثاني = Sheet.get_Range ("A2"، مفقود. / / احصل على جميع الخلايا إلى النطاق المناسب = Range.get_end (Excel.xldirection.xltoright)؛ // احصل على جميع الخلايا أسفل النطاق = Range.get_end (Excel.xldirection.xldown)؛ // الحصول على عنوان سلسلة خلية أقصى اليمين أسفل downaddress = range.get_address (false، false، excel.xlreferEcstyle.xla1، type.missing، type.missing.missing)؛ // الحصول على مجموعة كاملة من نطاق البيانات = Sheet.get_Range ("A2"، DownAddress)؛ // الحصول على مجموعة 2D من جميع قيم البيانات = (كائن [،]) Range.Value2؛ } الصيد (استثناء ه) {loggingservice.log (e.message)؛ } أخيرا {// تنظيف النطاق = null؛ ورقة = فارغة إذا (كتاب! = NULL) Book.Close (False، Missing.Value، Misking.Value)؛ كتاب = فارغة إذا (التطبيق! = null) app.quit ()؛ التطبيق = null؛ } إرجاع القيم؛
هل كانت مفيدة؟

المحلول

لست متأكدا مما إذا كانت هذه هي مشكلتك أم لا، ولكنها قد تكون جيدا. أنت لا تنظف كائنات Excel الخاصة بك بشكل صحيح. هم رمز غير مدار ويمكن أن يكون صعبا لتنظيفه. وأخيرا يجب أن تبدو مثل هذا: وكما أشارت التعليقات بالعمل مع Excel من ASP.NET ليست فكرة جيدة. رمز التنظيف هذا هو من تطبيق WinForm:

 GC.Collect();
 GC.WaitForPendingFinalizers();


 System.Runtime.InteropServices.Marshal.FinalReleaseComObject(range);
 System.Runtime.InteropServices.Marshal.FinalReleaseComObject(sheet);
 System.Runtime.InteropServices.Marshal.FinalReleaseComObject(book);

 WB.Close(false, Type.Missing, Type.Missing);

 Excel.Quit();
 System.Runtime.InteropServices.Marshal.FinalReleaseComObject(Excel);

تعديل

سيكون بديلا لاستخدام ADO.NET لفتح المصنف.

            DataTable dt = new DataTable();

            string connectionString;
            System.Data.OleDb.OleDbConnection excelConnection;
            System.Data.OleDb.OleDbDataAdapter da;
            DataTable dbSchema;
            string firstSheetName;
            string strSQL;

            connectionString = @"provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filename + @";Extended Properties=""Excel 12.0;HDR=YES;IMEX=1""";
            excelConnection = new System.Data.OleDb.OleDbConnection(connectionString);
            excelConnection.Open();
            dbSchema = excelConnection.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, null);
            firstSheetName = dbSchema.Rows[0]["TABLE_NAME"].ToString();
            strSQL = "SELECT * FROM [" + firstSheetName + "]";
            da = new OleDbDataAdapter(strSQL, excelConnection);
            da.Fill(dt);

            da.Dispose();
            excelConnection.Close();
            excelConnection.Dispose();

نصائح أخرى

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

إذا كنت تستطيع البقاء بعيدا عن التطبيقات وتحليل الملف بنفسك (باستخدام MS Libraries، فقط XML)

سوف تعمل في الكثير من المتاعب باستخدام Interop من ASP.NET. ما لم يكن هذا مخصصا لبعض التطبيقات الصغيرة في المنزل، سيكون من المستحسن عدم المضي قدما فيه.

Office Interop ليس برنامج أبقي برمجة بالمعنى التقليدي - إنه نظام الماكرو المكتبي الذي تم نقله إلى الحد الأقصى، مع القدرة على العمل في العمل - على سبيل المثال يمكن أن تتفاعل ماكرو Excel مع Outlook.

بعض عواقب استخدام Interop هي:

  • أنت فعلا فتح نسخة كاملة من تطبيق Office.
  • يتم تنفيذ أفعالك من خلال التطبيق كما لو أن المستخدم الذي بدأه المستخدم - وهذا يعني بدلا من رسائل الخطأ التي يتم إرجاعها في التعليمات البرمجية، يتم عرضها في واجهة المستخدم الرسومية.
  • نسختك من التطبيق يغلق فقط إذا كنت تقوم بذلك بشكل صريح - وحتى الآن، يمكن أن تمنع الأخطاء من الحدوث في الواقع (قد يقدم التطبيق "هل تريد حفظ" الحوار إذا لم تقم برجما بإخبار Excel أن التغييرات لا تحتاج إليها التغييرات ليتم حفظها). يؤدي هذا عادة إلى ترك العديد من النسخ المخفية من Excel قيد التشغيل على النظام - إدارة المهام المفتوحة ومعرفة عدد عمليات Excel.exe التي تعمل.

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

بعض البدائل تشمل:

  • استخدام تنسيقات Microsoft Office 2007 XML القائمة، بحيث يمكنك كتابة ملفات XML بنفسك.
  • استخدام streationsheetgear.net., ، وهو قارئ / كاتب ملف .NET ثنائي Excel (لا تحتاج إلى تثبيت Excel مثبتا، لأنها مستقلة تماما). نماذج StreedShetGear نفسها بعد واجهات InterTop لإنشاء تحويل رمز أقدم أسهل.

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

لقد لاحظت أن النطاق كان جدول البيانات بأكمله على الرغم من (من A2 إلى IV65536 أو أي شيء). لست متأكدا مما إذا كان المقصود.

شيء واحد يمكن أن تحاول استخدامه هو الورقة .usedrange، التي ستقلل على عدد الخلايا التي تقوم بتحميلها.

زوجين إضافيين أشياء صغيرة تعلمتها التي قد تجدها مفيدة:

  • استخدام التطبيق بدلا من التطبيقات
  • استخدم Marshal.FinalReleAsecomObject (Range) (وأيضا للورق أو الكتاب أو التطبيق) وإلا سيكون لديك عملية Excel.exe الخاصة بك.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top