2011-01-07 3 views
0

Ich habe eine vorhandene Delphi-Desktop-App, die ich als eine asp.net mvc app umschreiben werde.Wie kann ich eine Excel-Datei von asp.net mvc aktualisieren und speichern?

Die Desktop-App verfügt über 120 Excel-Berichte. Diese Berichte enthalten in der Regel nur wenige benannte Zellen mit Konfigurationsinformationen (Client-ID usw.), einige Datenabfragen, die auf SQL Server-Daten zurückgehen, und einige zentrale Tabellen.

Um einen Bericht über den Desktop-App, verwende ich OLE-Automatisierung

  1. öffnen Sie den Bericht
  2. bevöl benannten Zellen mit den richtigen Daten
  3. Verwendung ActiveWorkbook.RefreshAll(), um Update-Abfragen zu erzeugen und Pivot-Tabellen
  4. Speichern Sie den Bericht

Ich mag würde dies in m tun y Webanwendung. Die automatische Automatisierung wird jedoch nicht auf dem Server unterstützt und funktioniert nicht. Keine der Excel-Komponenten, die ich gesehen habe, scheint das Aktualisieren der Abfragen und/oder der zentralen Tabellen zu unterstützen.

Derzeit scheint meine beste Option, die Berichte mit einigen Berichtserstellungsprogramm neu zu erstellen und diese in Excel zu exportieren. Die resultierenden Dateien benötigen jedoch länger zum Schreiben, haben weniger Funktionalität (keine zentralen Tabellen) und natürlich gibt es 120 davon.

Vorschläge, wie ich meine vorhandenen Berichte verwenden kann?

aktualisieren

Excel auf dem Server installiert ist, die gleiche Version wie auf dem Entwicklungscomputer.

Mein mvc-Code ist so etwas wie:

objApp = new Application(); 
objBooks = objApp.Workbooks; 
objBook = objBooks.Open(FileName); 
objApp.DisplayAlerts = false; // don't warn if pivot table changed 
objApp.ActiveWorkbook.RefreshAll(); 
objBook.SaveAs(newFileName); 

Auf der Dev-Maschine fein es funktioniert, aber auf dem Server nicht auf der ersten Zeile

objApp = new Application(); 

mit System.UnauthorizedAccessException: Suchen Die COM-Klassenfactory für Komponente mit CLSID {00024500-0000-0000-C000-000000000046} ist aufgrund des folgenden Fehlers fehlgeschlagen: 80070005 Zugriff verweigert. (Ausnahme von HRESULT: 0x80070005 (E_ACCESSDENIED)).

Antwort

0

Sie haben Recht, es wird definitiv nicht von MS unterstützt. Die Ole-Automatisierung sollte jedoch auf dem Server funktionieren. Hier ist eine blöde Frage: Hast du Excel auf dem Server installiert? Können Sie Ihren Beispielcode senden? Normalerweise verwende ich die Interops. Hier ein kurzes Beispiel: http://dotnetperls.com/excel.

4

Ich habe nicht mit Charts gearbeitet, aber ich empfehle EPPlus gründlich, die für die Erstellung von Excel-Dateien eine Open-Source-Bibliothek ist.

+0

Upvote auf dem EPPlus. Große Bibliothek, aber begrenzte Pivot-Tabellen-Unterstützung von dem, was ich herausgefunden habe. – iivel

5

Das ist ein ziemlich häufiger Fehler, erfordert aber eine Reihe von Punkten auf dem Server für die Verwendung mit ASP.NET festgelegt werden. Im Allgemeinen werden die Empfehlungen auf diesen Thread genügen: System.UnauthorizedAccessException: Retrieving the COM class factory for Word Interop fails with error 80070005..

Es scheint nicht, dass diese richtig und gründlich behandelt wurden. Late-Binding könnte auch ein Teil des Problems sein.

+0

Ich habe diese Links durch, aber ich habe immer noch den Fehler. Ich verwende IIS 7.0. Ich habe die dcom Excel.Application-Berechtigungen für Netzwerkdienst und IIS_IUSRS festgelegt. Immer noch keine Freude. – SeanX

+0

Ich habe Excel 2003 auf dem Server und 2007 auf meinem Computer. Allerdings habe ich meinen Code neu geschrieben, um die späte Bindung zu verwenden. Eine Test-.net-App kann Excel laden und aktualisieren. Asp kann immer noch nicht :(. – SeanX

+0

Antwort war nicht was Asker suchte, also Bearbeitung es. –

2

Werfen Sie einen Blick auf NPOI

+0

Sieht nicht aus wie ich bestehende Berichte aktualisieren kann. – SeanX

1

Sie haben Recht, Sie wollen wahrscheinlich nicht OLE-Automatisierung auf dem Server zu tun. Nur das Risiko, dass Speicherlecks auftreten und Excel-Instanzen im Hintergrund nicht verwaltet werden, ist kein Problem.

Wir haben gute Erfahrungen mit Aspose.Cells. Vielleicht unterstützt es die Refresh-Funktion, nach der Sie suchen?

1

Ich fand diese Klasse vor ein paar Monaten, die ich verwenden, um Excel zu schreiben, ohne Excel zu verwenden. Es funktioniert wie ein Zauber und ich benutze es in vielen ASP.net-Anwendungen. Ich kann mich ehrlich gesagt nicht erinnern, wo ich es bekommen habe, also kann ich diese Person nicht erschaffen, obwohl sie das alles verdient.

/// <summary> 
/// Produces Excel file without using Excel 
/// </summary> 
public class ExcelWriter 
{ 
private Stream stream; 
private BinaryWriter writer; 

private ushort[] clBegin = { 0x0809, 8, 0, 0x10, 0, 0 }; 
private ushort[] clEnd = { 0x0A, 00 }; 


private void WriteUshortArray(ushort[] value) 
{ 
    for (int i = 0; i < value.Length; i++) 
     writer.Write(value[i]); 
} 

/// <summary> 
/// Initializes a new instance of the <see cref="ExcelWriter"/> class. 
/// </summary> 
/// <param name="stream">The stream.</param> 
public ExcelWriter(Stream stream) 
{ 
    this.stream = stream; 
    writer = new BinaryWriter(stream); 
} 

/// <summary> 
/// Writes the text cell value. 
/// </summary> 
/// <param name="row">The row.</param> 
/// <param name="col">The col.</param> 
/// <param name="value">The string value.</param> 
public void WriteCell(int row, int col, string value) 
{ 
    ushort[] clData = { 0x0204, 0, 0, 0, 0, 0 }; 
    int iLen = value.Length; 
    byte[] plainText = Encoding.ASCII.GetBytes(value); 
    clData[1] = (ushort)(8 + iLen); 
    clData[2] = (ushort)row; 
    clData[3] = (ushort)col; 
    clData[5] = (ushort)iLen; 
    WriteUshortArray(clData); 
    writer.Write(plainText); 
} 

/// <summary> 
/// Writes the integer cell value. 
/// </summary> 
/// <param name="row">The row number.</param> 
/// <param name="col">The column number.</param> 
/// <param name="value">The value.</param> 
public void WriteCell(int row, int col, int value) 
{ 
    ushort[] clData = { 0x027E, 10, 0, 0, 0 }; 
    clData[2] = (ushort)row; 
    clData[3] = (ushort)col; 
    WriteUshortArray(clData); 
    int iValue = (value << 2) | 2; 
    writer.Write(iValue); 
} 

/// <summary> 
/// Writes the double cell value. 
/// </summary> 
/// <param name="row">The row number.</param> 
/// <param name="col">The column number.</param> 
/// <param name="value">The value.</param> 
public void WriteCell(int row, int col, double value) 
{ 
    ushort[] clData = { 0x0203, 14, 0, 0, 0 }; 
    clData[2] = (ushort)row; 
    clData[3] = (ushort)col; 
    WriteUshortArray(clData); 
    writer.Write(value); 
} 

/// <summary> 
/// Writes the empty cell. 
/// </summary> 
/// <param name="row">The row number.</param> 
/// <param name="col">The column number.</param> 
public void WriteCell(int row, int col) 
{ 
    ushort[] clData = { 0x0201, 6, 0, 0, 0x17 }; 
    clData[2] = (ushort)row; 
    clData[3] = (ushort)col; 
    WriteUshortArray(clData); 
} 

/// <summary> 
/// Must be called once for creating XLS file header 
/// </summary> 
public void BeginWrite() 
{ 
    WriteUshortArray(clBegin); 
} 

/// <summary> 
/// Ends the writing operation, but do not close the stream 
/// </summary> 
public void EndWrite() 
{ 
    WriteUshortArray(clEnd); 
    writer.Flush(); 
} 
} 

Kopieren Sie diesen Code in eine CS-Datei.

Hier ist ein Beispiel

ExcelWriter writer = null; 
    FileStream stream = null; 
    string result = string.Empty; 

     string filepath = path; 
     DateTime sd = Convert.ToDateTime(sdate); 
     DateTime ed = Convert.ToDateTime(edate); 
     string daterange = sd.Month.ToString() + sd.Day.ToString() + sd.Year.ToString() + "_" + ed.Month.ToString() + ed.Day.ToString() + ed.Year.ToString(); 
     string xls = filepath + filename + "_" + daterange + ".xls"; 

     if (File.Exists(xls)) 
     { 
      File.Delete(xls); 
     } 

     stream = new FileStream(xls, FileMode.Create); 
     writer = new ExcelWriter(stream); 
     writer.BeginWrite(); 

     //write header 

     writer.WriteCell(0, 0, "text"); 
     writer.WriteCell(0, 1, "text"); 
     writer.WriteCell(0, 2, "text"); 


     //write data 
     int row = 1; 

     //Open Connection 
     OpenDBConnection(); 

     //get Case List 
     List<Int32> caseList = getCaseList(sdate, edate); 

     foreach (Int32 caseid in caseList) 
     { 
      writer.WriteCell(row, 0, caseid); 
      writer.WriteCell(row, 1, caseid); 
      writer.WriteCell(row, 2, caseid); 
      row++; 
     } 

     writer.EndWrite(); 
     stream.Close();` 
+0

Dies würde mit neuen Berichten helfen, aber wird mir nicht mit meinem bestehenden Excel helfen – SeanX

1

Wahrscheinlich hast du das gleiche Problem, was ich vor ein paar Monaten. Das Problem besteht darin, dass Microsoft Excel als COM-Objekt standardmäßig nur von Administrator-, System- oder Interactive-Konten aktiviert werden kann.

Hier eine detaillierte Lösung ist, arbeitete für mich: http://blog.crowe.co.nz/archive/2006/03/02/589.aspx

Hoffnung, das hilft.

ps: Was ist mit OLE DB, ist es möglich, den Code für die Verwendung von OleDbConnection zu ändern?

+0

THanks: Ich habe es versucht, aber ich bekomme immer noch den gleichen Fehler. – SeanX

Verwandte Themen