2016-05-24 15 views
3

Ich habe eine Anfrage von einem Client, um eine Excel-Tabelle aus einer Abfrage zu generieren. Ich habe die Abfrage, die Felder ausschießt, und ich kann die Excel-Datei ohne eine Störung erzeugen. Das Problem tritt auf, wenn der Client diese Excel-Datei nimmt und dann versucht, sie zu manipulieren.Kann mit ColdFusion keine geeignete Excel-Tabelle erstellen

Der Großteil der Probleme kommt von Feldern, die als Währung oder Daten markiert werden sollten. Ich bin mit einigen Schwierigkeiten in der Lage, ein "echtes" Datumsfeld zu erzeugen. Vorher hat Excel die Daten nicht richtig sortiert. Ich konnte mit dem folgenden Code eine Excel-Formel aufrufen. DateValue zwingt Excel, dies als ein echtes Datumsfeld zu bestätigen. Dies schlägt jedoch fehl, wenn diese Datei über Excel bearbeitet wird.

<cfset SpreadsheetSetCellFormula(s 
      ,"DATEVALUE(#Chr(34)##Replacement_ETD##Chr(34)#)" 
      , therow 
      , 9)> 

Das nächste Problem ist das Währungsfeld. Ich kann Excel nicht dazu bringen, die Werte als Währung anzuerkennen. Es kommt immer kundenspezifisch vor. Wenn dies festgelegt ist, funktioniert die SUM-Funktion in Excel nicht. Sie können die Felder einzeln wie A1+B1+C1 = TOTAL hinzufügen. Dies ist jedoch nicht hilfreich, wenn 200 Zeilen vorhanden sind.

Ich konnte einen Vorschlag von einem anderen CF-Programmierer bekommen, der eine ähnliche Situation hatte. Er erzeugte die Excel-Datei zuerst mit den richtigen Überschriften und setzte die Spalten in ihre richtigen Felder wie Datum und Währung, etc.

Der nächste Schritt wäre, die Felder Zeile für Zeile auszufüllen und sie sollten richtig formatiert sein.

Code:

<cfset filename = expandPath("./reports/arrivals.xlsx")> 
<cfspreadsheet action="read" src = "#filename#" name = "s" > 
<cfset therow = 0> 
<cfoutput query="myExcel" startrow="1"> 
    <cfset therow = myExcel.currentrow + 1> 
    <cfset SpreadsheetSetCellValue(s, Incumbent, therow, 1)> 
    <cfset SpreadsheetSetCellValue(s, Section, therow, 2)> 
    <cfset SpreadsheetSetCellValue(s, Position_Number, therow, 3)> 
    <cfset SpreadsheetSetCellValue(s, Position_Title, therow, 4)> 
    <cfset SpreadsheetSetCellValue(s, Incumbent_Emplyment_Type, therow, 5)> 
    <cfset SpreadsheetSetCellValue(s, Incumbent_ETD, therow, 6)> 
    <cfset SpreadsheetSetCellValue(s, Tour_Comments, therow, 7)> 
    <cfset SpreadsheetSetCellValue(s, Replacement, therow, 8)> 
    <cfset SpreadsheetSetCellValue(s, Replacement_ETA, therow, 9)> 
</cfoutput>  
<cfheader name="content-disposition" value="attachment; filename=Departures_(#DateFormat(now(),'mmddyy')#).xls"> 
<cfcontent type="application/msexcel" variable="#spreadsheetReadBinary(s)#" reset="true"> 

Die Daten in den Zellen bereits richtig formatiert. Wenn diese Datei generiert und an den Benutzer gestreamt wird, werden die Spalten nicht wie erwartet formatiert.

Weiß jemand, ob diese Methode funktioniert oder einen besseren Vorschlag hat, wie CF ein korrektes Datums- und Währungsfeld für Excel erstellen kann?

Adobe Coldfusion v10 läuft auf RHEL 5.

Per Anfrage Hier ist ein Code queryNe w, dass die Verwendung wird Codedaten und Währung generieren.

Schritt eins: Ich erstellte eine Excel-Datei mit der ersten Zeile eingefroren und es hat die Spaltenüberschrift. Die erste Spalte wurde als das Datum bezeichnet, an dem das Format ein langes Datum ist - mm/dd/yyy; Spalte zwei ist Dollar, der auf Währung gesetzt wurde.

Ich lese diese Datei dann füllen Sie die Zeilen und streamen die Datei an den Benutzer zum Download.

<cfset filename = expandPath("./reports/Test.xlsx")> 

<cfspreadsheet action="read" src = "#filename#" name = "s" > 

<cfset myQuery = QueryNew("MyDate, Dollar", "Date, Decimal")> 

<cfset newRow = QueryAddRow(MyQuery, 5)> 

<cfset temp = QuerySetCell(myQuery, "MyDate", "03-11-2000", 1)> 
<cfset temp = QuerySetCell(myQuery, "Dollar", "403.45", 1)> 

<cfset temp = QuerySetCell(myQuery, "MyDate", "01-01-2009", 2)> 
<cfset temp = QuerySetCell(myQuery, "Dollar", "603.22", 2)> 

<cfset temp = QuerySetCell(myQuery, "MyDate", "09-21-2013", 3)> 
<cfset temp = QuerySetCell(myQuery, "Dollar", "103.55", 3)> 

<cfset temp = QuerySetCell(myQuery, "MyDate", "01-15-2005", 4)> 
<cfset temp = QuerySetCell(myQuery, "Dollar", "3.33", 4)> 

<cfset temp = QuerySetCell(myQuery, "MyDate", "07-22-2003", 5)> 
<cfset temp = QuerySetCell(myQuery, "Dollar", "13.75", 5)> 

<cfset therow = 0> 
<cfoutput query="myQuery" startrow="1"> 
    <cfset therow = myQuery.currentrow + 1> 

    <cfset SpreadsheetSetCellValue(s, DateFormat(MyDate, 'mm/dd/yyyy'), therow, 1)> 
    <cfset SpreadsheetSetCellValue(s, Dollar, therow, 2)> 
    #myQuery.currentrow# <br> 
    #myQuery.MyDate# <br> 
    #myQuery.Dollar# <br> 
</cfoutput>   

<cfheader name="content-disposition" value="attachment; 
        filename=Departures_(#DateFormat(now(),'mmddyy')#).xls"> 
<cfcontent type="application/msexcel" variable="#spreadsheetReadBinary(s)#" reset="true"> 

Sie können die Datei in MS Excel oder in Google Tabellen öffnen. Test eins, mit der ersten eingefrorenen Zeile sollten wir in der Lage sein, nach dem Datumsfeld zu sortieren. Meine Ergebnisse sind: Die Daten werden nicht richtig sortiert. In Spalte 2 mit der Währung, wenn wir versuchen, eine SUMME zu machen, die funktioniert! Dies hatte vorher nicht funktioniert, aber jetzt.

Wenn ich versuche, die Datei zu öffnen, bekomme ich die Warnung, dass diese Datei beschädigt ist und Excel versucht, sie zu öffnen. Ich erhalte keine solche Warnung in Google Tabellen.

+0

Sätze wie „versagt“ und „wird nicht funktionieren“ sind sehr eindeutig. Kannst du bitte ein kleines, [* stand alone * Beispiel] (http://stackoverflow.com/help/mcve) bereitstellen, das wir testen können, das zeigt das Problem? Tipp: Sie können 'QueryNew()' verwenden, um eine manuelle Abfrage zu generieren, sodass das Beispiel keine Datenbankabfrage erfordert. – Leigh

+0

@Leigh sure thing. Ich werde das Beispiel aufpeppen und bearbeiten. – weggie

+0

@Leigh Der Code ist ein Beispiel aktualisiert und meine Ergebnisse aus diesem Test. Vielen Dank. – weggie

Antwort

0

CF kann beim Arbeiten mit Datumszellen ein wenig eigenartig sein. Excel ist ziemlich gut darin, den richtigen Zelltyp zu erraten, wenn ein Wert manuell eingegeben wird. Mit CF ist es jedoch etwas komplizierter. Da CF relativ typenlos ist, stimmen Werte und Zelltypen nicht immer korrekt überein.Das Verwenden von Funktionen, die ein Abfrage-Objekt anstelle von SpreadsheetSetCellValue() verwenden, erzeugt normalerweise bessere Ergebnisse. Wahrscheinlich, weil Query-Objekte Werte und Datentypen enthält. Ab CF11 unterstützt SpreadsheetSetCellValue einen neuen Datenparameter, mit dem Sie sowohl den Wert als auch den Zelldatentyp angeben können. Da Sie CF10 verwenden, verwenden Sie stattdessen SpreadsheetAddRows, um die Werte zu füllen.

In Bezug auf die Warnung, dass die Datei beschädigt ist, wird durch die Tatsache verursacht, dass der tatsächliche Dateiinhalt und die Dateierweiterung im Download-Code nicht übereinstimmen. Der Code liest in einer .xlsx Datei, aber der Download behauptet, es ist ein. xls (Anwendung/Msexcel) Datei. Stellen Sie sicher, dass die beiden übereinstimmen, um den Fehler zu beheben.

Hier ist ein funktionierendes Beispiel mit CF11 getestet

<!--- 
    Test.xlsx contains two columns, with headers on row 1 
    - Column A format: *m/d/yyyy 
    - Column B format: number with 2 decimal places 
---> 
<cfspreadsheet action="read" src="c:/temp/Test.xlsx" name="sheet" > 

<cfset myQuery = QueryNew("")> 
<cfset QueryAddColumn(MyQuery, "Dollar", "Decimal", [ 403.45, 703.22, 103.55, 3.33, 13.75] )> 
<cfset QueryAddColumn(MyQuery, "MyDate", "date", [ parseDateTime("2000-03-11", "yyyy-mm-dd") 
               , parseDateTime("2009-01-01", "yyyy-mm-dd") 
               , parseDateTime("2013-09-21", "yyyy-mm-dd") 
               , parseDateTime("2005-01-15", "yyyy-mm-dd") 
               , parseDateTime("2003-07-22", "yyyy-mm-dd")]) > 

<cfset spreadsheetAddRows(sheet, myQuery)> 
<cfset spreadsheetFormatColumn(sheet, {dataFormat="m/d/yy"}, 1)> 
<cfset spreadsheetFormatColumn(sheet, {dataFormat="##,####0.00"}, 2)> 

<cfheader name="content-disposition" value="attachment; filename=Departures_(#DateFormat(now(),'mmddyy')#).xlsx"> 
<cfcontent type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" variable="#spreadsheetReadBinary(sheet)#" reset="true"> 
+0

Danke für die Hilfe! Ich kann bestätigen, dass mit dieser Methode alles "sauber" rauskommt. – weggie