7

F# と Excel Interop を使用してデータを Excel スプレッドシートに出力しています。私の最初のアプローチは、各セルを個別に設定することでした:

worksheet.Range(range1).Value2 <- "=sum(a1:a10)"
worksheet.Range(range2).Value2 <- "=min(a1:a10)"
worksheet.Range(range3).Value2 <- "=max(a1:a10)"
(* etc *)

ただし、数式が多数ある場合、これは遅すぎるため、配列に切り替えました。

worksheet.Range(range).Value2 <- [| "=sum(a1:a10)"
                                    "=min(a1:a10)"
                                    "=max(a1:a10)" |]

また

worksheet.Range(range).Formula <- [| "=sum(a1:a10)"
                                     "=min(a1:a10)"
                                     "=max(a1:a10)" |]

ただし、現在、Excel は数式の値を計算する代わりに、これらの文字列をセルに表示するだけです。私も試しました:

worksheet.Range(range).FormulaArray <- [| "=sum(a1:a10)"
                                          "=min(a1:a10)"
                                          "=max(a1:a10)" |]

しかし、それは各フォーミュラのターゲット範囲を台無しにしました. 何が起こっているのかわかりません。(そのままにしておく代わりに"a1:a10"、Excel は数式がどこにあるかに基づいてターゲット範囲を変換しました。)

これを行うより良い方法はありますか?

更新:「=MIN($G$2:$G$5)」も使用してみましたが、Excel が文字列を表示するだけで数式を評価しないという同じ効果が得られました。

価値があるのは、セルを入力して数式の任意の文字を消去してから再度追加すると、「入力」を押すと、Excel がそれを評価することです。

更新 2 : 次のことも試しました。

worksheet.Range(range).FormulaR1C1 <- [| "=sum(R2C[0]:R4C[0])"
                                          "=average(R2C[0]:R4C[0])"
                                          "=min(R2C[0]:R4C[0])"
                                          "=max(R2C[0]:R4C[0])" |]

しかし、同じ問題が発生します。Excel は数式を評価するのではなく、それらを文字列としてレンダリングします。

4

4 に答える 4

8

ダニエルの答えは機能するはずですが、R1C1 形式の数式を使用する方が簡単だと思います。これを使用するには、コードは次のようになります。

ws.Range(range).FormulaR1C1 <- [| "=sum(R1C1:R10C1)";
                                  "=min(R1C1:R10C1)"; 
                                  "=max(R1C1:R10C1)" |]

これにより、絶対アドレスを含む式が生成されます。R[vertical_offset]C[horizo​​ntal_offset] を使用して相対アドレスを作成できます。行または列全体を選択するのも簡単です。R1 は最初の行全体、C4 は「D」列全体です。

R1C1 アドレスの作成は、純粋な F# で String.Format または sprintf を使用すると簡単です。

編集: vbaで簡単にチェックしましたが、機能しません。Excelは、範囲内の各セルに最初の配列要素を入れています。いずれにせよ、R1C1 アドレッシング ポイントは引き続き有効です。これはヘッダー式 (つまり、ws.Range(headerRange).FormulaR1C1 <- "=sum(R2C[0]:R10C[0]")) の魅力のように機能するため、回答はそのまま残します。

EDIT2 : ArrayFormula は配列数式用だと思うので、どちらも機能しません。

EDIT3:私はいくつかの調査を行い、不可能だと思っていたことに対する答えを見つけました:)。

まず、この文字列を数式として配置するには、それらをオブジェクトにアップキャストします。

let formulas : obj[] = [| "=sum(R1C1:R10C1)";
                          "=min(R1C1:R10C1)"; 
                          "=max(R1C1:R10C1)" |]

それを FormulaR1C1 に入れます。

ws.Range(range).FormulaR1C1 <- formulas

第二に、重要な部分: 上記の例では、範囲が 3 つのセル (つまり、F3:H3) の水平方向の範囲であると想定しています。垂直範囲 (つまり、F3:F5) に配置しようとすると、合計式が範囲内のすべてのセルで繰り返されることがわかります。この場合、数式は 2 次元オブジェクト配列である必要があり、外部配列の最初の行は数式の配列であるはずですが、range.FormulaR1C1 に入れようとしているときに SafeArrayTypeObjectExtension を取得しています。このmsdn docsを見てください:

範囲が 1 次元または 2 次元の範囲である場合、数式を同じ次元の Visual Basic 配列に設定できます。同様に、数式を Visual Basic 配列に入れることができます。

この例外については後でもう一度説明します。

于 2012-09-18T20:42:11.020 に答える
1

最初のアプローチが機能し、遅いということは、入力するのが遅すぎる(実行しない)ことを意味すると仮定すると、このようなセルの束を更新する方が速く/簡単かもしれません

[
  range1, "=sum(a1:a10)"
  range2, "=min(a1:a10)"
  range3, "=max(a1:a10)"
  ...
]
|> List.iter (fun (range, value) -> worksheet.Range(range).Value2 <- value)
于 2012-09-18T21:17:48.400 に答える
1

または、fsnip.net http://fssnip.net/aVのこのスニペットからいくつかのアイデアを得ることができます。これは、Excel の高次関数を実装しています。(スニペットは実際にはパフォーマンスに関するものではないため、これはスプレッドシート ギアを使用するよりも長いショットのパフォーマンスです。)

于 2012-09-18T21:26:35.087 に答える
0

Excel 内でパフォーマンスの問題を回避できない場合は、SpreadsheetGear (http://www.spreadsheetgear.com/) を検討することをお勧めします。これは実質的に Excel API 全体を複製しますが、はるかに高速になる可能性があります。(もう 1 つの利点 - サーバーで実行するものを開発している場合、サーバーに Excel をインストールする必要はありません。)

于 2012-09-18T21:20:09.893 に答える