Computeメソッド sum()および型objectの使用が無効です

データテーブルをComputeメソッドで集計させようとしていますが、
エラー sum()および型objectの使用が無効です が出てきます。
対処法を教えていただければありがたいです。

集計.Compute(“sum(金額)”,String.Empty)

Computeメソッドの引数 filterについては、何も設定したくありません。
null としたいのですが、nullの設定はエラーになるため、String.Emptyとしています。

1 Like

おそらく使用しているのが、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)

1 Like

ご対応感謝いたします。
サンプルコードは問題なく実行できました。

ところが実装して試してみたところ
エクセルの行が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設定して、変数に集計値を集めました。

これでうまくいきました。
ありがとうございます。