Domanda

Questo era funzionante...e ho spostato il codice di smaltimento nel blocco finale, e ora fallisce ogni volta.

Ho un foglio di calcolo di prova con 4 record, lungo 6 colonne.Ecco il codice che sto usando per inserirlo.Questo è ASP .Net 3.5 su IIS 5 (il mio PC) e su IIS 6 (server web).

Esplode sulla linea subito prima della presa:"valori = (oggetto [,]) intervallo.value2;" Con il seguente errore:

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

Qualche idea?Suggerimenti?Ho ottenuto la maggior parte di questo codice da codeproject, quindi non ho idea se questo sia il modo corretto di lavorare con Excel.Grazie per tutto l'aiuto che potete fornire.

Ecco il mio codice:

Excel.ApplicationClass app = null;
Excel.Workbook book = null;
Excel.Worksheet sheet = null;
Excel.Range range = null;

object[,] values = null;

try
{
    // Configure Excel
    app = new Excel.ApplicationClass();
    app.Visible = false;
    app.ScreenUpdating = false;
    app.DisplayAlerts = false;

    // Open a new instance of excel with the uploaded file
    book = app.Workbooks.Open(path);

    // Get first worksheet in book
    sheet = (Excel.Worksheet)book.Worksheets[1];

    // Start with first cell on second row
    range = sheet.get_Range("A2", Missing.Value);

    // Get all cells to the right
    range = range.get_End(Excel.XlDirection.xlToRight);

    // Get all cells downwards
    range = range.get_End(Excel.XlDirection.xlDown);

    // Get address of bottom rightmost cell
    string downAddress = range.get_Address(false, false, Excel.XlReferenceStyle.xlA1, Type.Missing, Type.Missing);

    // Get complete range of data
    range = sheet.get_Range("A2", downAddress);

    // get 2d array of all data
    values = (object[,])range.Value2;
}
catch (Exception e)
{
    LoggingService.log(e.Message);
}
finally
{
    // Clean up
    range = null;
    sheet = null;

    if (book != null)
        book.Close(false, Missing.Value, Missing.Value);

    book = null;

    if (app != null)
        app.Quit();

    app = null;
}

return values;
È stato utile?

Soluzione

Non sono sicuro che questo sia il tuo problema o meno, ma potrebbe benissimo esserlo.Non stai ripulendo correttamente i tuoi oggetti Excel.Si tratta di codice non gestito e può essere difficile da ripulire.Alla fine dovrebbe assomigliare a questo:E come hanno notato i commenti, lavorare con Excel da asp.net non è una buona idea.Questo codice di pulizia proviene da un'app 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);

MODIFICARE

Un'alternativa sarebbe utilizzare ado.net per aprire la cartella di lavoro.

            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();

Altri suggerimenti

Creare/distruggere Excel su ogni richiesta avrà prestazioni assolutamente terribili indipendentemente da ciò che fai.In generale, eseguire qualsiasi app di Office utilizzando l'automazione è una brutta faccenda per molte ragioni (vedi Qui).L'unico modo per farlo funzionare è avere una singola istanza dell'app (nel mio caso Word) che viene inizializzata una volta e quindi le richieste vengono accodate a questa istanza per l'elaborazione

Se puoi stare lontano dalle app e analizzare il file da solo (usando le librerie MS, solo di XML)

Incontrerai molti problemi utilizzando l'interoperabilità da ASP.NET.A meno che questo non sia pensato per qualche piccola applicazione interna, sarebbe consigliabile non procedere con esso.

Office Interop non è un'API di programmazione nel senso tradizionale - è il sistema macro di Office portato al suo massimo, con la capacità di lavorare tra processi - ad esempio una macro di Excel potrebbe interagire con Outlook.

Alcune conseguenze dell'utilizzo dell'interoperabilità sono:

  • In realtà stai aprendo una copia completa dell'applicazione Office.
  • Le tue azioni vengono eseguite dall'applicazione come se fossero state avviate da un utente: ciò significa che invece di essere restituiti messaggi di errore nel codice, vengono visualizzati nella GUI.
  • La tua copia dell'applicazione si chiude solo se la comandi esplicitamente e anche in questo caso gli errori possono impedire che ciò accada effettivamente (l'applicazione potrebbe presentare una finestra di dialogo "vuoi salvare" se non hai detto a Excel in modo programmatico che le modifiche non sono necessarie essere salvato).Ciò di solito comporta che molte copie nascoste di Excel vengano lasciate in esecuzione nel sistema: aprire il task manager e vedere quanti processi excel.exe sono in esecuzione.

Tutto ciò rende l'interoperabilità qualcosa da evitare per le normali applicazioni desktop e qualcosa che dovrebbe essere utilizzato solo come ultima risorsa per le applicazioni server, poiché un popup della GUI che richiede un'azione o uno script che fa trapelare il processo è un omicidio in un ambiente server.

Alcune alternative includono:

  • Utilizzo dei formati basati su XML di Microsoft Office 2007, in modo da poter scrivere autonomamente i file XML.
  • Utilizzando Foglio di calcoloGear.Net, che è un lettore/scrittore di file binari Excel .NET (non è necessario che Excel sia installato, poiché è completamente autonomo).SpreadsheetGear si modella secondo le interfacce Intertop per rendere più semplice la conversione del codice precedente.

Probabilmente l'errore è esattamente quello che dice, stai ricevendo un errore di memoria esaurita.Prova a suddividere il caricamento dell'array di valori in più parti più piccole invece di ottenere l'intero intervallo in una volta.Ho provato il tuo codice in C# e non ho riscontrato problemi, ma il foglio di calcolo che stavo caricando era quasi vuoto.

Ho notato però che Range era l'intero foglio di calcolo (da A2 a IV65536 o qualcosa del genere).Non sono sicuro che sia previsto.

Una cosa che potresti provare a utilizzare è sheet.UsedRange, che ridurrà il numero di celle che stai caricando.

Un paio di piccole cose aggiuntive che ho imparato e che potresti trovare utili:

  • Utilizzare Application anziché ApplicationClass
  • Usa Marshal.FinalReleaseComObject(range) (e anche per fogli, libri, app) altrimenti il ​​tuo processo EXCEL.EXE rimarrà bloccato.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top