データテーブルをComputeメソッドで集計させようとしていますが、
エラー sum()および型objectの使用が無効です が出てきます。
対処法を教えていただければありがたいです。
集計.Compute(“sum(金額)”,String.Empty)
Computeメソッドの引数 filterについては、何も設定したくありません。
null としたいのですが、nullの設定はエラーになるため、String.Emptyとしています。
データテーブルをComputeメソッドで集計させようとしていますが、
エラー sum()および型objectの使用が無効です が出てきます。
対処法を教えていただければありがたいです。
集計.Compute(“sum(金額)”,String.Empty)
Computeメソッドの引数 filterについては、何も設定したくありません。
null としたいのですが、nullの設定はエラーになるため、String.Emptyとしています。
おそらく使用しているのが、ExcelのReadRangeから作成したDataTableだと思うのですが、その場合、各列(Column)のタイプは全てObject型になります。
(これはExcelが仕様として「列の型」を持っていないためです)
Object型から数値型への暗黙の変換はできないので、そのエラーが出てしまいます。
対策としては、LINQを使う、または既存の(型設定がされた)DataTableに値を埋め込む、ぐらいしか思いつかないです……。
または既存の(型設定がされた)DataTableに値を埋め込む
の方向ですが、
代入を2つ並べて、
1つ目
左:捨てる用変数 右:集計.Columns.Add(“集計用”, GetType(Decimal), “CONVERT(金額,System.Decimal)”)
※集計用列を追加する為用なので、左側の変数は使いませんのでなんでもよいです。
※型に関しては仕様しだいです。
2つ目
左:結果 右:集計.Compute(“sum(集計用)”,String.Empty)
でいけると思います。
※数値が入っているはずの列(金額)に空白がある場合はうまくいきません。
ExcelをまんまRead Rangeさせて、Data Tableを使おうとしました。
ご指摘の通りです。
いろいろと案を出していただき、大変感謝しています。
対応してみます。
変数s1としてColumns.Add(“集計用”, GetType(Decimal), “CONVERT(金額,System.Decimal)”)
をAssignアクティビティに書きましたが、エラーが出ます。
メッセージ:無効な引数 関数 Convert()
“CONVERT(金額,System.Decimal)”を削除すればエラーは解消され、
”集計用”列が 元のデータテーブル”集計”に追加されます。
もちろん、その場合、追加された集計用列の値には何も入りません。
この場合、列に値を入れるにはどうしたらよいのでしょうか?
ご教授ありがとうございます。
LINQ の書き方を教えていただけますとありがたいです。
こちらのForumでサンプルコードを入手して動作するのを確認しましたが、
今回のケースにどのようにあてはめてよいのかわかりませんでした。
集計というテーブルには、”金額”列以外に”集計用”という列を追加しました。
その列は空欄です。
細かい原理を書き始めると、たぶん原稿用紙何枚オーダーになってしまうので、とりあえずサンプルだけ。
集計.AsEnumerable().Sum(Function(r) Int32.Parse(r("金額").ToString()))
これでInt32型に変換した上での合計値がとれます。
UiPath 18.4用のサンプルも添えておきます、確認してみてください。
ExcelSumSample.zip (7.6 KB)
ご対応感謝いたします。
サンプルコードは問題なく実行できました。
ところが実装して試してみたところ
エクセルの行が2行までは問題なく実行し、結果が出るのですが、
3行の場合、3行でも問題ない場合もありますが、
以下のエラーが出る場合もあります。
4行以上になると必ず以下のエラーが出ます。
行は任意の追加で、固定されているわけではなく、増減します。
全く同じレコードで実施しても同様の結果となります。
System.FormatException
入力文字列の形式が正しくありません。
この不安定性は一体何なのでしょう?
行(レコード)3つの場合に、エラーになったり、エラーが出なかったりと
どうしてそうなるのか、わかりません。
もちろん構文エラーがあるわけではありません。
必要があれば情報を提供いたします。
このような回答で申し訳ありませんが、何らかのコメントを
いただけますとありがたいです。
上のサンプルですが、中身で
Int32.Parse(r("金額").ToString())
という処理をしています。
これは「金額」フィールドの値を(文字列にした上で)Int型に変換する処理なのですが、おそらく「金額」の列に、数値以外の値(文字)や、値が入っていない行があるのではないかな、と思います。
それを適切に処理しようとすると、UiPathでやるには(LINQでできなくもないですが、かなり複雑な式になるので)For Each Rowでループさせて集計するほうが無難なように思えます。
Honoka様
ご回答ありがとうございます。ご指摘了解しました。そこで
データテーブル”集計”の金額列について、For eachの中に
Assingアクティビティ
左辺:row(”金額”) 右辺:Convert.ToInt32(row(“金額”))
を入れてループを回してみました。
ループ後、テーブルの中を見ましたが、
レコードはすべて数値になっているようでした。
それでもう一度、実行したのですが、同様の症状が出ています。
LINQはあきらめるとして、
そこで Assignアクティビティで左辺:変数
右辺:集計.Compute(“Sum(金額)”, String.Empty)
によって金額を合計してみました。
これでも当初と同様のsum()および型objectの使用が無効ですと
エラーでます。
ループでObject型をInt32型に変換しているはずですが、
どうしてでしょうか?
For Each Row ループを使う集計とご指摘されているのは、別の
方法でしょうか? そうであれば、お手数おかけして申し訳ありませんが
ご教授いただけますと、ありがたいです。
こんにちは
@Honoka さんの推察どおりおそらく対象データにInt変換できないもの(この場合空文字?)の存在が怪しいかと思います。
ちょっと美しくないですが、無名関数の部分を
Function(r) ( If( Int32.TryParse(r("金額").ToString,intTemp) ,Int32.Parse(r("金額").ToString) , 0 ) )
としてみて、結果が想定のものと同等かを確認いただければと思います。
(Int変換できないものを0として扱っています。)
(事前にintTempの変数をInt32型で宣言しておいてください。)
ご指摘ありがとうございます。
確認したところ、スクレイピングしたデータに
数値で処理できないものが混じる場合がありました。
取り除いたところ、LINQで正常に処理できました。
(Honoka様 Yuichi様 ありがとうございます)
しかしながらComputeでは、処理できません。
ループで型を変更しているはずなのですが、
皆さん、Computeをどのように使っておられるのでしょうか
差し支えない範囲でヒントをいただければありがたいです。
こんにちは
型変換を
で実施している、
としているのであれば、これでは実体としては型が変換されていません。
Honokaさんのreplyにもあります通り、DataTableのColumnには型が定義されており、その型がObject型のままなので、値も依然としてObject型の扱いになります。
ループさせているなら、あらかじめ加算用のInt32変数(仮にintSum)を用意して
ループの中で
左辺 intSum
右辺 intSum + Convert.ToInt32(row(“金額”))
のようにすればよいのではと思います。
あるいは、Int32型の列を追加して、そこに変換した値を入れてやって、Computeするなどになります。(がかえって面倒と思います。)
Yoichi様
ありがとうございます。
ご教授ありがとうございます。実際に設定してみました。
ところがエラーになります。
Row(“金額”)が使えるのは、For Each Row でデータテーブル“集計”をセットした場合です。そのループの中に、intSumを設定すると、“列intSumが見つかりません”というエラーになります。intSumをデータテーブル“集計”の中にあらかじめ列として定義していてもエラーが消えることはありません。
そこで、このFor Each Rowの中に、For Eachを入れ子で設定し、For EachにIn row.ItemArrayを設定します。そこでintSum intSum+Convert.ToInt32(集計.Rows(“金額”)) としようとします。これによって構文エラーとはならないのですが、ところが実行時に“Stringからintへの暗黙の型変換できません“という
エラーに阻まれます。
ご指摘の設定をおこなってエラーにならないようにするには、一体どのようにすればよろしいのでしょうか、ご指摘いただけますとありがたいです。
こんにちは
Row(“金額”)が使えるのは、For Each Row でデータテーブル“集計”をセットした場合です。そのループの中に、intSumを設定すると、“列intSumが見つかりません”というエラーになります。intSumをデータテーブル“集計”の中にあらかじめ列として定義していてもエラーが消えることはありません。
状況が正確に把握できないため、画像なりをつけていただいた方が良いかもですが、記載いただいた内容からしますと、まずは以下をチェックいただく必要があるかと思います。
1. intSum が変数パネルで Int32型として定義されているか。またそのスコープは適切か。
2.For Each Row のループでは DataTableとして集計、変数としてrowが指定されている場合、
集計.Rows(“金額”)
ではなく
row(“金額”)
として記述する必要があります。
そのためAssignアクティビティ(代入)の
左辺 intSum
右辺 intSum + Convert.ToInt32(rows(“金額”))
となっていることを確認ください。
Yoichi様
誠実なご対応、感謝いたします。
変数スコープもrowの扱いも問題はありませんでした。
いただいたご指示をうまく消化できていませんでした。
集計テーブルに”集計用”という列をint32型で定義した後で、
for reach row ループで、
intSum=intSum+Convert.toInt32(row(”金額”))
row(“集計用”)=intSum
という2本のAssignを設定します。
そしてループの外に
集計.Compute(”sum(集計用)”,String.Empty)
とAssign設定して、変数に集計値を集めました。
これでうまくいきました。
ありがとうございます。