AppleScriptでPowerPointを操作する Part2｜表の操作



[前回の記事](https://qiita.com/yuoya/items/314489c6c6c893cc7597)で、AppleScriptでPowerPointの図形（Shape）の操作について紹介しました。
PowerPointの表を操作する内容について書いてみたら非常に長くなってしまいましたので、別記事としました。
基本的な内容は前回の記事を参照してください。
https://qiita.com/yuoya/items/314489c6c6c893cc7597


## 環境

- macOS 11.4 (Big Sur)
- PowerPoint for Mac 16.49（Office 365、2021）

## 目指すところ

PowerPointの表において、以下のような操作を実現する
* 表を生成（ダイアログで行数と列数を指定、書式も事前に設定）
* 列の追加（選択部分の左に列を追加。列数はダイアログで指定）
* セルの結合（選択部分について）

![表の作成.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115422/d5ffd25a-6ab4-2c2a-387b-cdf0a9f5030a.gif)

### 作成しようと思った背景
まず一つには、標準の表については細かいスタイル設定ができず、毎回表を作成してはスタイルを設定する必要がありました。これを改善しようと思ったのが最初の動機です。

列の追加やセルの結合は標準の機能で用意されており、そちらの方が動作が早いものの、ショートカットの割り当てができないため、StreamDeck等の左手デバイスで使えないという問題があり、今回合わせて作成しました。

### 表の生成

表の生成も基本的には図形の生成とほとんど同じです。
ただ行数、列数に自由度があるため、それを外から変えられるようにすること、
また枠線の設定については少し特殊な操作が必要なことが違います。

#### とりあえず3x3の表を生成

図形の時と同じように選択ページに3x3の表を生成してみましょう。

```applescript
tell application "Microsoft PowerPoint"
	
	-- 表の位置とサイズ、行数列数を設定
	set x_position to 30
	set y_position to 30
	set dia_width to 100
	set dia_height to 100
	set n_row to 3	-- 行数：3
	set n_col to 3		-- 列数：3
	
	--現在のスライド番号を取得
	set n to slide index of slide range of selection of active window
	--現在のスライド内で操作
	tell slide n of active presentation		
		-- tableを生成し、TheShapeTableと命名
		set TheShapeTable to make new shape table at the end with properties {number of columns:n_col, number of rows:n_row, left position:x_position, top:y_position, width:dia_width, height:dia_height}
	end tell
end tell

```

#### 行数と列数をダイアログから取得する

ダイアログ自体は`display dialog`を用いれば簡単に生成し、値を取得することが可能です。
ただし一つのダイアログで複数変数を取得することはできません。
そこでカンマ区切りで表現し、2つの値を同時に得ることとします。

```applescript
display dialog "作成する行,列を数字で入力" default answer "3,3"
set ans to text returned of result
```

`ans`にカンマを含んだ文字列が格納されます。
これを分割してそれぞれの値にします。
文字列の区切りに対して、AppleScriptにはdelimitersが用意されているのでこれを用います。

```applescript
	set org_delimi to text item delimiters of AppleScript -- オリジナルの区切り文字をとっておく
	set text item delimiters of AppleScript to "," -- ","で区切る
	set ans1 to text item 1 of ans -- １つめの値を変数ans1 に格納
	set ans2 to text item 2 of ans -- 2つめの値を変数ans2 に格納
	set text item delimiters of AppleScript to org_delimi -- 操作終了後にオリジナルの区切り文字に戻す
```



#### 行数と列数を指定した表の生成

それではここまで合わせたコードを作成してみましょう。

```applescript
tell application "Microsoft PowerPoint"
	
	-- 表の位置とサイズを設定
	set x_position to 15
	set y_position to 15
	set dia_width to 300
	set dia_height to 100
	
	display dialog "作成する行,列を数字で入力" default answer "3,3"
	set ans to text returned of result
	
	--文字列の分割（ダイアログでカンマ区切りで入れた行と列を取得するため）
	set org_delimi to text item delimiters of AppleScript -- オリジナルの区切り文字をとっておく
	set text item delimiters of AppleScript to "," -- ","で区切る
	set n_row to text item 1 of ans -- 1つめの値を変数n_rowに格納
	set n_col to text item 2 of ans -- 2つめの値を変数n_colに格納
	set text item delimiters of AppleScript to org_delimi -- 操作終了後にオリジナルの区切り文字に戻す	
	
	set n to slide index of slide range of selection of active window --現在のスライド番号を取得
	tell slide n of active presentation --現在のスライド内で操作
		-- tableを生成し、TheShapeTableと命名
		set TheShapeTable to make new shape table at the end with properties {number of columns:n_col, number of rows:n_row, left position:x_position, top:y_position, width:dia_width, height:dia_height}
	end tell
end tell
```
任意の行と列数の表を作成できるようになりました。



#### 書式の設定

次に表の書式設定をしていきます。
VBAでは**表のスタイル**でタイトル行や縞模様の有無などを設定できるのですが、AppleScriptでそれに該当するものは見当たりませんでした。
地道にセル一つずつに書式を設定していきます。
背景色やフォント、アライメントなどはShapeの時と同じように、セルの中のプロパティを一つずつ設定すればよいのですが、枠線についてはセルのプロパティとして直接編集することができません。
`get border`を用いて、セルの中の枠線（上、左、下、右、右斜め斜線、左斜め斜線）を設定し、それぞれにline formatを設定していく必要があります。

```applescript
tell cell xx of row xx of table object --セル（xx,xx）内で操作
					set vertical anchor of text frame of shape of it to anchor middle --左上詰めを中央に変更
					set font size of font of text range of text frame of shape of it to 14 --フォントサイズを14に
					set font color theme index of font of text range of text frame of shape of it to second dark theme color --文字色をdark2に
					set fore color of fill format of shape of it to {234, 234, 234} -- 背景色をグレーに
					set alignment of paragraph format of text range of text frame of shape of it to paragraph align center --文字のアライメントを中央揃えに
					-- ●枠線の設定（上）
					set currentCell to get it
					set topBorder to get border currentCell edge top border
					set line weight of topBorder to 1
					set fore color of topBorder to {200, 200, 200}
					-- ●枠線の設定（左）
					set leftBorder to get border currentCell edge left border
					set line weight of leftBorder to 1
					set fore color of leftBorder to {200, 200, 200}
					-- ●枠線の設定（右）
					set rightBorder to get border currentCell edge right border
					set line weight of rightBorder to 1
					set fore color of rightBorder to {200, 200, 200}
					-- ●枠線の設定（下）
					set bottomBorder to get border currentCell edge bottom border
					set line weight of bottomBorder to 1
					set fore color of bottomBorder to {200, 200, 200}		
					
				end tell
```



#### 表の生成（最終版）

ダイアログで、行数と列数を確認し、それに合わせた表を生成しています。
タイトル行、それ以外の行についてそれぞれフォント、アライメント、背景色、枠線の書式設定を行っています

```applescript
tell application "Microsoft PowerPoint"
	
	set x_position to 15
	set y_position to 15
	set dia_width to 300
	set dia_height to 100
	

	
	display dialog "作成する行,列を数字で入力" default answer "3,3"
	set ans to text returned of result
	
	
	--文字列の分割（ダイアログでカンマ区切りで入れた行と列を取得するため）
	set org_delimi to text item delimiters of AppleScript -- オリジナルの区切り文字をとっておく
	set text item delimiters of AppleScript to "," -- ","で区切る
	set ans1 to text item 1 of ans -- １つめの値を変数ans1 に格納
	set ans2 to text item 2 of ans
	set text item delimiters of AppleScript to org_delimi -- 操作終了後にオリジナルの区切り文字に戻す
	
	--display dialog "ans1:" & ans1 & ", ans2:" & ans2
	
	set n_row to ans1
	set n_col to ans2
	
	
	set n to slide index of slide range of selection of active window --現在のスライド番号を取得
	tell slide n of active presentation --現在のスライド内で操作
		-- tableを生成し、TheShapeTableと命名
		set TheShapeTable to make new shape table at the end with properties {number of columns:n_col, number of rows:n_row, left position:x_position, top:y_position, width:dia_width, height:dia_height}
		
		--　●tableの書式を設定
		tell TheShapeTable
			
			-- ●タイトル行の書式設定
			set nr to 1
			repeat with nc from 1 to n_col
				tell cell nc of row nr of table object --セル内で操作
					set content of text range of text frame of shape of it to "R" & nr & "C" & nc --文字入力
					set vertical anchor of text frame of shape of it to anchor middle --左上詰めを中央に変更
					set font size of font of text range of text frame of shape of it to 14 --フォントサイズを14に
					set font color theme index of font of text range of text frame of shape of it to second dark theme color --文字色をdark2に
					set fore color of fill format of shape of it to {234, 234, 234} -- 背景色をグレーに
					set alignment of paragraph format of text range of text frame of shape of it to paragraph align center --文字のアライメントを中央揃えに
					-- ●枠線の設定（上）
					set currentCell to get it
					set topBorder to get border currentCell edge top border
					set line weight of topBorder to 1
					set fore color of topBorder to {200, 200, 200}
					-- ●枠線の設定（左）
					set leftBorder to get border currentCell edge left border
					set line weight of leftBorder to 1
					set fore color of leftBorder to {200, 200, 200}
					-- ●枠線の設定（右）
					set rightBorder to get border currentCell edge right border
					set line weight of rightBorder to 1
					set fore color of rightBorder to {200, 200, 200}
					-- ●枠線の設定（下）
					set bottomBorder to get border currentCell edge bottom border
					set line weight of bottomBorder to 1
					set fore color of bottomBorder to {200, 200, 200}
					
					
				end tell
			end repeat
			
			-- ●一般行の書式設定
			repeat with nr from 2 to n_row
				repeat with nc from 1 to n_col
					tell cell nc of row nr of table object --セル内で操作
						set content of text range of text frame of shape of it to "R" & nr & "C" & nc --文字入力
						set vertical anchor of text frame of shape of it to anchor middle --左上詰めを中央に変更
						set font size of font of text range of text frame of shape of it to 14 --フォントサイズを14に
						set font color theme index of font of text range of text frame of shape of it to second dark theme color --文字色をdark2に
						set fore color of fill format of shape of it to {255, 255, 255} -- 背景色を白に
						--●セル内テキストの設定
						tell paragraph format of text range of text frame of shape of it	
							set alignment of it to paragraph align center --文字のアライメントを中央揃えに
							set line rule within of it to true --行間の設定を行の倍数に
							set space within of it to 1.1 --行間を1.1倍に
							set line rule before of it to false --段落前の設定をポイントに
							set space before of it to 3 --段落前を3ポイントに
						end tell
						
						-- ●枠線の設定
						set currentCell to get it
						-- ●枠線の設定（左）
						set leftBorder to get border currentCell edge left border
						
						set line weight of leftBorder to 1
						set fore color of leftBorder to {200, 200, 200}
						-- ●枠線の設定（右）
						set rightBorder to get border currentCell edge right border
						set line weight of rightBorder to 1
						set fore color of rightBorder to {200, 200, 200}
						-- ●枠線の設定（下）
						set bottomBorder to get border currentCell edge bottom border
						set line weight of bottomBorder to 1
						set fore color of bottomBorder to {200, 200, 200}
						
					end tell
				end repeat
			end repeat
			
		end tell
	end tell
	
end tell
```



### 表に行追加

#### log機能について

AppleScriptの`log`機能を用いて、どのセルが選択されているかを見ていきます。
`log`機能の使い方は、
`start log`を入れておき、出力したいところで
`log "xx"`と記述するだけです。
ログを見るためにはスクリプトエディタのメニューより「ウィンドウ」＞「ログの履歴」を表示しておく必要があります。
ログが表示されるのは[メッセージ]タグです。

#### 選択しているセルの確認

AppleScriptでは選択セルをそのままオブジェクトで返してくる機能はないようです。ただしセルが選択されているかどうかを真偽値で表すプロパティは存在します。全てのセルをスキャンし、選択されているかどうかを確認してリストに格納します。

```applescript
tell application "Microsoft PowerPoint"
	start log
	
	tell shape table 1 of shape range of selection of active window
		set n_row to number of rows	--表の行数
		set n_col to number of columns	--表の列数
		set selListR to {}	--選択された行のリスト
		set selListC to {}	--選択された列のリスト
		
		--どこが選択されているかをSCAN ------
		repeat with nr from 1 to n_row	--行をSCAN
			repeat with nc from 1 to n_col	--列をSCAN
				tell cell nc of row nr of table object
					if selected of it then	--選択されているかどうかの判定
						set end of selListR to nr
						set end of selListC to nc
						log "R" & nr & "C" & nc & " is Selected!"
					end if
				end tell
			end repeat
		end repeat
	end tell
	log selListR
	log selListC
end tell
```


#### 行の追加（行の分割）

行を追加するコマンドが見当たらなかったため、セルの分割で擬似的に行追加としています。

特定のセル（XX列、YY行目）をX行、Y列に分割するコードは以下のようになります。
`split cell XX of row YY number of rows X number of columns Y`
Yを1にし、全ての列に対して同じ行数分、分割をすることで、行の追加とほぼ同じ状態となります。



#### 行の追加（最終版）

現在選択している上の行に対して行を追加するコードを記述していきます。
追加行数をダイアログで入力可能にしています。さらに現在の選択セル数を元に、デフォルトの行数を設定するようにしてみました。
また分割をするとセルの大きさが小さくなってしまうことがあるため、その対策も入れています。



```applescript
tell application "Microsoft PowerPoint"
	start log
	
	tell shape table 1 of shape range of selection of active window
		set n_row to number of rows
		set n_col to number of columns
		set selListR to {}
		
		--どこが選択されているかをSCAN ------
		repeat with nr from 1 to n_row
			repeat with nc from 1 to n_col
				tell cell nc of row nr of table object
					if selected of it then
						set end of selListR to nr
						log "R" & nr & "C" & nc & " is Selected!"
					end if
				end tell
			end repeat
		end repeat
		-- 選択されている行を抜き出し-----
		set firstRow to first item of selListR
		set lastRow to last item of selListR
		set numRow to (lastRow - firstRow + 1)
		display dialog "挿入する行数" default answer numRow
		set numRow to text returned of result
		log "numRow is " & numRow
		
		
		tell table object
			
			--選択位置のセルの高さを取得
			set cellHeight to height of row (firstRow - 1)
			set cellHeight2 to height of row lastRow
			log "Hight is " & cellHeight
			log "Hight2 is " & cellHeight2
			
			--行全体の分割（ほぼ行追加）			
			repeat with nc from 1 to n_col
				--split cell nc of row 2 number of rows 3 number of columns 1
				split cell nc of row (firstRow - 1) number of rows (numRow + 1) number of columns 1
			end repeat
			--分割したセルの高さを元に戻す
			set height of row (firstRow - 1) to cellHeight
		end tell
	end tell
end tell

```

### 表のセル結合

#### 選択しているセルの確認
先程の行追加とほぼ同じやり方で選択セルを確認します。
前回は行だけわかればよかったのですが、今回は行と列を両方取得しますので、
リスト`selList`を数値でなく、セルオブジェクトのリストとしています。

#### セルの結合
セルをAAとセルBBを結合するコードは以下です。
`merge AA merge with BB`
AAとBBは隣接している必要はありません。AAを左上、BBを右下とするその中の選択範囲に入る全てのセルがマージ対象となります。

#### セルの結合（選択範囲に対して）
これらを踏まえてセル結合のコードは以下になります。

```applescript
tell application "Microsoft PowerPoint"
	start log
	tell shape table 1 of shape range of selection of active window
		set n_row to number of rows
		set n_col to number of columns
		
		set selList to {}
		
		--どこが選択されているかをSCAN ------
		repeat with nr from 1 to n_row
			repeat with nc from 1 to n_col
				tell cell nc of row nr of table object
					if selected of it then
						set currentCell to get it
						log currentCell
						--選択範囲を保存
						set end of selList to currentCell
						
						log "R" & nr & "C" & nc & " is Selected!"
					end if
				end tell
			end repeat
		end repeat
		-- 選択されているセルを抜き出し-----
		--選択されたセルの左上と右下（選択リストの最初と最後を選択）		
		set firstCell to first item of selList
		set lastCell to last item of selList
		
		--　そのセルを結合
		merge firstCell merge with lastCell
		
		
	end tell
end tell
```

## 関連記事

https://qiita.com/yuoya/items/314489c6c6c893cc7597


## 参考リンク

PowerPointの表をAppleScriptで取得（+Excelとの連携）
https://www.tactsystem.co.jp/blog/post-101/

AppleScript全般
http://tonbi.jp/AppleScript/

AppleScript文字列の分割
https://blog.goo.ne.jp/vallie/e/54a08f7082cca4364c5d3eb48fa96447