質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.58%

poworshellでexcelを操作する場合、既に値が入力されているセルに追記する事は可能でしょうか?

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 2,305

jimuma

score 20

 実現したい事

powershellでexcelを操作し、セルに値を入力します。その際、既に値が入力されているセルに対して、入力されている値を上書きせずに、追記するようなセルへの入力方法を知りたいです。

 バージョンと扱えるツール

具体的な挙動の検証ではなく、ソースコードの記述をするにあたっての方向性(考え方?)が分かれば問題ないのでバージョンは問いません。
また、仕事上の制限がある為、利用出来るのはpowershellとexcelであり、他のソフトウェアや開発言語は利用出来ません。

 具体例

説明が長くなってしまうので恐縮ですが、スクリプトを書く事自体初心者ですので、どなたか詳しい方がいらっしゃれば是非アドバイス頂きたいです。

実現したい事の詳細としては下記のように
1、「管理台帳.xlsx」のA列からユーザ名を取得し、
2、「実機のID.txt」から「抜き出したユーザが所属しているグループ」を抜き出し
3、「管理台帳.xlsx」のB列に「ユーザが所属しているグループ」を入力したいと考えています。

「実機のID.txt」の見方ですが「<」で始まる「fruit」と「OS」がグループ名で
それ以外はユーザ名とします。つまり、
orange,plum,strawberry,appleはfruitグループに属しているユーザで
apple,linux,andoroidはOSグループに属しているユーザとします。

尚、処理の概要としては3つ目の画像のように、例えば「linux」の属しているグループを
探す場合は、「実機のID.txt」をGet-Contentで取得し一行ずつ上の行から見ていき、
「linux」ユーザが見つかったら今度はそこから上方向に「<」を探していき
該当すれば「ユーザが所属しているグループ」として取得する、ような感じです。

詳細はスクリプトをご覧ください。

一応、これでほぼ上手くいったのですが問題が発生しました。
ユーザ名「apple」のように「fruit」グループにも「OS」グループにも属しているユーザの場合、
「管理台帳.xlsx」のように一つのセルに「fruit OS」と入力出来ず、「fruit」のみに
なってしまいます。(恐らく最初に合致した「OS」グループを「fruit」で上書いている為)

そこで、「管理台帳.xlsx」のappleユーザのように、複数のグループに属しているユーザに対しては、
一つのセルに二つのグループ名を記入する方法を教えて欲しいです。

長くなり恐縮ですが、宜しくお願い致します。

イメージ説明

イメージ説明

イメージ説明

$EXCELPATH = "C:\work\ユーザ別グループ管理台帳.xlsx" 
$excel = New-Object -ComObject Excel.Application 
$excel.Visible = $true 
$book = $excel.Workbooks.Open("$EXCELPATH") 
$sheet = $excel.Worksheets.Item(1) 

$TEXT = "C:\work\実機のID.txt" 
$DATA = Get-Content $TEXT 

for($col = 2; $col -le 9; $col++){                                        #2行目~9行目まで繰り返す 
$ID = $sheet.Cells.Item($col,1).Text                                      #A列のセルに記載されているユーザ名の取得 
        for($i = 0; $i -lt 9; $i++){                                      #1行目から9行目まで繰り返す 
                if($ID -eq $DATA[$i]){                                    #「$ID」と「$i」行目が等しいかチェック 
                        for($j = $i; $j -gt 0; $j--){                     #「$j」に「$i」を入れて、「0」まで遡る 
                                if($DATA[$j] -match "< "){                #「$i」行目に「<」が含まれているかチェック 
                                        $GROUP1 = $DATA[$j] -replace '< ','' 
                                        $GROUP2 = $GROUP1 -replace ' >','' 
                                        echo "$ID が所属しているグループは $GROUP2 です。" 
                                        $sheet.Cells.Item($col,10) = $GROUP2 #特定のセルに、取得したセルの値を入力 
                                        break 
                                        }else{ 
                                        ; 
                                        } 
                                } 
                }else{ 
                        ; 
                } 
        }         
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

次のスクリプトでできると思います。
当然のことながら、ここに挙げられたサンプルでしか動作テストしていませんので、実際に使っているファイルを直接書き換える前にテストをしてください。

$excelPath = 'Excel ファイルのフルパス'
$idPath = 'C:\work\実機のID.txt'

$g = @{}
Get-Content $idPath | Where-Object { $_ -ne "" } | Foreach-Object {
    if ($_ -match '^<(.*)>$') {
        $currentGroup = $Matches[1]
    } else {
        if ($g[$_] -ne $null) {
            $g[$_] += "`n"
        }
        $g[$_] += $currentGroup
    }
}
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $true
$book = $excel.Workbooks.Open($excelPath)
$sheet = $excel.Worksheets.Item(1)
for ($row = 2; ; $row++)
{
    $id = $sheet.Cells.Item($row, 1).Text
    if ($id -eq "") {
        break
    }
    $sheet.Cells.Item($row, 2).Value = $g[$id]
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/20 16:32

    有難うございます!
    教えて頂いたソースコードの「$g[$_] += $currentGroup」の後ろにechoコマンドで「 $g[$_]」に
    格納されている値を確認したところ「apple」のユーザに対しては「fruit」と「OS」グループが
    セットされていた事が確認出来たので、これで行けそうです!

    改行コードを付与する条件の「if ($g[$_] -ne $null) 」が何故「apple」の所だけ合致するのか、
    その前の「$Matches[1]」が何をするためなのか等、不明な点はあるのですが、
    パイプやハッシュテーブルなど学習しながら理解していきたいと思います!
    有難うございました!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.58%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る