3

クライアントから、クエリから Excel スプレッドシートを生成するように依頼されました。フィールドを追い出すクエリがあり、問題なく Excel ファイルを生成できます。問題は、クライアントがその Excel ファイルを取得し、それを操作しようとしたときに発生します。

問題の大部分は、通貨または日付としてマークする必要があるフィールドから発生します。私は、「実際の」日付フィールドを生成することができます。以前は、Excel で日付が正しく並べ替えられていませんでした。以下のコードを使用して、Excel 数式を呼び出すことができました。DateValueExcel がこれを実際の日付フィールドとして認識するように強制します。ただし、このファイルを Excel で操作すると失敗します。

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

次の問題は通貨フィールドです。Excel に値を通貨として認識させることができません。それは常にカスタムになります。これが設定されている場合、SUM関数は Excel で動作しません。のようにフィールドを個別に追加できますA1+B1+C1 = TOTAL。ただし、200 行ある場合、これは役に立ちません。

同様の状況にある別の CF プログラマーから提案を得ることができました。最初に、適切な見出しを付けて Excel ファイルを生成し、列を日付や通貨などの適切なフィールドに設定しました。

次のステップは、フィールドを行ごとに入力することであり、適切にフォーマットする必要があります。

コード:

<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">

セル内のデータは既に適切にフォーマットされています。このファイルが生成されてユーザーにストリーミングされると、列が期待どおりにフォーマットされません。

この方法が機能するかどうか、またはCFにExcelが認識できる適切な日付と通貨フィールドを生成するためのより良い提案があるかどうか、他の誰かが知っていますか?

RHEL 5 で実行されている Adob​​e ColdFusion v10。

リクエストごとqueryNeに、コードの日付と通貨を生成する w を使用したコードを次に示します。

ステップ 1: 最初の行が固定され、列ヘッダーがある Excel ファイルを作成しました。列 1 は日付として指定されており、形式は長い日付 (mm/dd/yyy) です。列 2 は、通貨に設定されているドルです。

そのファイルを読み、行に入力し、ファイルをユーザーにストリーミングしてダウンロードします。

<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">

MS Excel または Google スプレッドシートでファイルを開くことができます。最初の行を固定してテストします。日付フィールドで並べ替えることができるはずです。私の結果は次のとおりです。日付が正しくソートされていません。列 2 の通貨で、動作する SUM を実行しようとすると! これは以前は機能していませんでしたが、現在は機能しています。

また、ファイルを開こうとすると、このファイルが壊れているという警告が表示され、Excel が開こうとします。Google スプレッドシートではそのような警告は表示されません。

4

1 に答える 1

1

日付セルを操作する場合、CF は少し風変わりです。Excel は、値が手動で入力されたときに正しいセルの種類を推測するのに非常に優れています。ただし、CF では少しトリッキーです。CF は比較的型がないため、値とセル型が常に正しく一致するとは限りません。通常、SpreadsheetSetCellValue() の代わりにクエリ オブジェクトを使用する関数を使用すると、より良い結果が得られます。最も可能性が高いのは、クエリ オブジェクトに値とデータ型の両方が含まれているためです。ただし、CF11 の時点では、SpreadsheetSetCellValueは新しいデータ パラメーターをサポートしており、値とセル データ型の両方を指定できます。CF10 を使用しているため、代わりにSpreadsheetAddRowsを使用して値を入力してみてください。

ファイルが破損しているという警告については、実際のファイルの内容とダウンロード コード内のファイル拡張子が一致していないことが原因です。コードは.xlsxファイルを読み込んでいますが、ダウンロードでは .xlsx であると主張しています。xls (アプリケーション/msexcel) ファイル。エラーを取り除くには、2 つが一致していることを確認してください。

これはCF11でテストされた実際の例です

<!---
    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">
于 2016-05-26T18:26:37.610 に答える