皆もすなるQiitaといふものを、儂もしてみむとてするなり。
と言う訳で、こん**は!はなっち!です。
昨日は、UiPathブログ発信チャレンジ2022サマーの1日目。
@saosao885の【TryCatchのハナシ(延長戦)~反省会とTerminate Workflowを使ってみる~】でしたね!
今日ははなっち!の番です!
この記事はUiPathブログ発信チャレンジ2022サマーの2日目の記事です。
【序章】
EXCELでもCSVからでもいいのですが、UiPathでデータを扱い際、DataTable型を中心に扱う事が多いと思います。例えば。売上明細データがあって、その売上日毎の合計値を求めたい。こういった場合は、EXCELの、PIVOTテーブル的なアクティビティを使って実装してあげるとか...( はなっち!のピボット風アクティビティパック をご覧ください)
時には、売上日毎の最後の行の下に、合計行を挿入したいなんて要望もあるかと思います。
EXCELで言えば、挿入したい場所の行をアクティブにして、右クリックして「挿入」し、
その空いた行に、SubTotalワークシート関数などを設定してあげればOK!
なのですが、ここはUiPathのQiitaですので、UiPathではどうやるのがいいか、ちょっと考えてみましょう!
【本題】
基本的に、DataTable型の間の行に直接行を挿入する事はできないと思っています(出来るとおっしゃる方、私に教えてください(^^♪)。
2022/7/10 追記
前の文章で、「直接行を挿入する事はできない」とありますが、これは筆者の無知のなせる発言で、実はちゃんとDataTable型変数.Rows.InsertAtと言うメソッドがあり、これを使えば、ちゃんと行の間に直接行を挿入する事で出来る」んです。ちょっと検証はしていませんので、その方法などは別のスレッドに書いてみます。ありがとうございます!
@Risa_Mizushinaさん
で、以降の内容は、Rows.InsertAtメソッドを使わない、別の方法を前提にしている、通常使うべきではない方法である事を前提にお読みください。
2022/7/10 追記終了
ですので、("SEQ列"のような)行の位置を陽に持たせて、 挿入する行の位置 の下に挿入するのだったら、その 挿入する行の位置+α の行の位置を設定した行を最終行に挿入し、
後で並べ替えをするのがセオリーかなと思っています(いや違う!とおっしゃる方、私に教えてください(^^♪)。
方法1(非推奨)
入力側のDataTableに、SEQ列(Int32型)を用意し、そこに増分を挿入行+1として、各行に値を設定していきます。
追加側のDataTableにも**SEQ列(Int32型)を用意し、挿入すべきSEQ番号+1の値を設定します。
その後、入力側のDataTableと、追加側のDataTableを併合してあげます。
最後に、SEQ列をキーにして、並び替えをしてあげれば、挿入されたことになりますね。
「繰り返し (各行)」アクティビティを使って、行の位置を計算しつつ(SEQ=SEQ+2でも、SEQ=現在のインデックス変数 * 2でも)、値を設定するのは、ちょっと手間っちゃ手間ですね。後付けの「データ列を追加」アクティビティだと、DataTableを出力した時、最終列になっているし。。。デバッグの時に美しくない!なんて方もいらっしゃるかもしれませんね。
方法2(非推奨)
「データ列を追加」アクティビティには、 自動インクリメント と言うパラメタがあります。
これは、行が追加されるたびに、その列に+1された値が自動的に設定される機能です。これなら、後で追加する行にも"n+α"してあげれば簡単そうですね。
やってみましょう!
まず、「データ列を追加」アクティビティで、 TypeArgumentにはDouble型、自動インクリメントはTrue とします。
この、”SEQ"列しかないDataTableに対して、入力側のDataTableを、「データ テーブルをマージ」アクティビティを使って、マージします。その際、 スキーマがない時の動作はAdd にします。
一方、追加側のDataTableにも、"SEQ"列を新たに追加して、そこに0.5などの値を設定します。
この状態で、「データ テーブルをマージ」アクティビティを使って、マージします
と、頭の中でのストーリーは完璧だったのですが、浅知恵でしたねぇ。。。自動インクリメントをTrueにすると、そのTypeArgumentはInt32型に修正されてしまうのです!
ですので、並び替えしても、合っているのかどうか、確証が持てません! この方法は使えません!
調査!
「データ列を追加」アクティビティには、 自動インクリメント と言うパラメタがありました。何か他にも設定できる何かがあるのでは?と思い、探ってみました!
- AllowDBNull これはパラメタの「DBNullを許可」ですね
- AutoIncrement これはパラメタの「自動インクリメント」ですね
- AutoIncrementSeed これは???「自動インクリメント」+「Seed(種)」ですね!?
- AutoIncrementStep これは???「自動インクリメント」+「Step(足踏み)」ですね!?
もしかして、 AutoIncrementSeedは自動インクリメントの開始の値、AutoIncrementStepは自動インクリメントの増分の値 ではないか?
やってみましょう!
この設定を施したDataTable型に対して、値のあるDataTableを「データ テーブルをマージ」アクティビティを使って、マージします。
"列A","列B","列名"の値は適当なのですが、"SEQ"の値は、確かに1から始まり、増分2となっていますね。
方法3(非推奨)
基本的には、方法2 と同じです。
まず、「データ列を追加」アクティビティで、 TypeArgumentにはInt32型、自動インクリメントはTrue とします。「代入」アクティビティを使って、該当列のパラメタ、AutoIncrementSeed には1を設定、AutoIncrementStep には2を設定します。
この、”SEQ"列しかないDataTableに対して、入力側のDataTableを、「データ テーブルをマージ」アクティビティを使って、マージします。その際、 スキーマがない時の動作はAdd にします。
一方、追加側のDataTableにも、"SEQ"列を新たに追加して、そこに1などのInt32型の値を設定します。
この状態で、「データ テーブルをマージ」アクティビティを使って、マージします
マージしたDataTable、「データ テーブルを並び替え」アクティビティを使って、並び替えします
うまくいきましたね!(机上で見せただけですが、裏ではキッチリ確認しています)
応用!(非推奨)
1行を追加挿入する事にしたので、AutoIncrementStep は2を設定しましたが、要件によっては2行追加挿入したいって事もあるかもしれませんね。その場合には、AutoIncrementStep は3を設定してあげればいいでしょう。
行が追加される度に、自動インクリメントがTrueとなった列の値には、AutoIncrementStep 分増えていくので、ここにマイナス値を設定すれば、減算されていくはずですね。
確かに、2ずつ減算された値が設定されていますね。
おわりに
いかがでした?
先に紹介した、使えない方法も含んで3つの方法。
他にも、入力DataTaleの行を一行ずつ中間DataTableにImportRowしていき、ある条件を満たした時に追加側のDataTaleの行を中間DataTableにImportRowする方法もありますね。こちらの方が正攻法かもしれません。
いずれにしても、中間DataTableなどを使う方法が楽かな?って印象です。ただ、その場合、中間DataTableのメモリも消費するので、扱うDataTableの列数、行数と相談してみてください。
「DataTableの行の間に、行を挿入する」ってタイトルでしたが、 AutoIncrementSeed 、AutoIncrementStepがある!使える!って事を覚えていただければと思います!
今回も読んでいただきありがとうございました!
是非UiPathでのロボ開発の一助になればと思っています。
ありがとうございました!