ドキュメントの不足
フリーウェア系ソフトによくあることだが、xlwingsも公式ドキュメントに書かれていることが不足している。
xlwingsに不足している機能を補うモジュールを作ろうとして、現状のxlwingsでどこまで出来るのかを確認することを意識しながら、ソースを読んでいて分かった。
公式ドキュメントのAPIのところに書いてあることは、ほとんどソースファイル中のdocstringとして書かれている。ただし、各クラスのメソッドのうち、__getitem__
などのアンダーバー2つで始まる特殊メソッドについては、公式ドキュメントに書かれていない。
rangeオブジェクトに配列アクセス
1次元配列としてのアクセス
下記の様に、添え字1つでアクセスすると、範囲内のセルを1次元的に並べた個々のセルに対してのrangeオブジェクトへのアクセスとなる。
import xlwings as xw
wb = xw.Book
rng = wb.sheets[0].range("A1:B2")
for i in range(len(rng)):
print(rng[i].address)
# -->
$A$1
$B$1
$A$2
$B$2
2次元配列としてのアクセス
上記の例に違和感を持った人もいると思う。rngは2次元の領域を持つゆえ、通常のpythonの2次元配列(リストのリスト)と同様であれば、rng[0].address
は$A$1:$B$1
を返すのであるから。
リストのリストとしてrngにアクセスすると、以下のようにエラーとなる。
print(rng[0][1])
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_19144\1066751280.py in <cell line: 1>()
----> 1 print(rng[0][1])
~\AppData\Roaming\Python\Python39\site-packages\xlwings\main.py in __getitem__(self, key)
2407 k = key + n if key < 0 else key
2408 if k < 0 or k >= n:
-> 2409 raise IndexError("Index %s out of range (%s elements)." % (key, n))
2410 else:
2411 return self(k + 1)
IndexError: Index 1 out of range (1 elements).
これは、rng[0]
が単一のセル$A$1
のみに対するrangeオブジェクトとなっているために生じているエラーである。
では、2次元的に扱いたい場合は、どうしたら良いか。xlwingsのソース中のclass range
の__getitem__
メソッドを見ると、2つの要素を持つtuple
に対応したコードが先頭にある。
2次元的にアクセスする正しい方法を以下の例のように、[ ]
内に行と列を並べて書く方法である。
nr,nc = rng.shape
for i in range(nr):
for j in range(nc):
print(rng[i,j].address)
# -->
$A$1
$B$1
$A$2
$B$2
__getitem__
メソッドの先頭にあるコードであることから、この方法がrangeオブジェクトに対する配列アクセスの本筋の方法だと思われる。
以下の例の様にrange内の一部の要素の書式を変更したい場合に、この様な配列アクセスを用いると良い。
rng[1,0].api.Font.Bold = True # セルA2を太字にする
なお、numpyと同様のスライスによるアクセスにも対応しているので、範囲内の特定の列のみなどのrangeオブジェクトを得たい場合に用いると良い。