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

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

新規登録して質問してみよう
ただいま回答率
85.48%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

10983閲覧

OpenpyxlによるExcelファイルの保存ができません

退会済みユーザー

退会済みユーザー

総合スコア0

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2017/09/10 16:41

編集2017/09/26 06:50

###状況・到達目標
PythonのライブラリOpenpyxlを使ってExcelファイルの編集をしようとしています。
動画から切り抜いた大量の画像約200枚(1枚320×180)を事前に用意しました。
それらを一度ビットマップ化してから各セルに対応する色を塗りつぶすことでExcelでドット絵を描いています。
このようにして、用意した大量の画像を順にドット絵化して、映画のフィルムのようにエクセル上に並べていきたいと思っています。

###該当のソースコード

Python

1# -*- coding:utf-8 -*- 2 3import cv2 4import glob 5from string import ascii_uppercase as AtoZ 6from openpyxl import load_workbook 7from openpyxl.styles import PatternFill 8 9image_path = '用意した画像の保存パス' 10#用意した画像の枚数 11number = 200 12 13''' 14エクセルの初期設定 15ビットマップ化したものを各セルに塗りつぶすためにセルの形を変形 16''' 17image = cv2.imread(image_path + '0.jpg') 18 19# エクセルファイル読み込み 20wb = load_workbook(filename='test.xlsx') 21# アクティブなシートを取り出す 22ws = wb.active 23 24# エクセルの列名リスト作成 25col_name = list(AtoZ) # 'A'~'Z' 26for i in range(len(image[0]) - 26): # 'AA'~ 27 col_name.append(AtoZ[i // 26] + AtoZ[i % 26]) 28 29for col in range(len(image[0])): 30 # 列の幅を変更 31 ws.column_dimensions[col_name[col]].width = 0.3 32 33 for row in range(len(image) * number): 34 # 行の高さを変更 35 ws.row_dimensions[row].height = 1.5 36 37 38''' 39各セルの塗りつぶし 40''' 41images = glob.glob(image_path + '*.jpg') 42 43next_row = 0 44count = 0 45 46for img_path in images: 47 image = cv2.imread(img_path) 48 49 for row in range(len(image)): 50 for col in range(len(image[row])): 51 # 赤、緑、青の値を青、緑、赤の順に16進数2桁ずつの文字列へ変換 52 red, green, blue = image[row][col] 53 color = '%02x%02x%02x' % (blue, green, red) 54 55 # 塗りつぶすセル名を取得 56 cell_name = col_name[col] + str(row + 1 + next_row) 57 # セル名をセット 58 cell = ws[cell_name] 59 # 塗りつぶし 60 cell.fill = PatternFill(patternType='solid', fgColor=color) 61 62 count += 1 63 64 next_row = count 65 66wb.save('test.xlsx')

###発生している問題
保存されたExcelファイルを開こうとすると

'test.xlsx'の一部の内容に問題が見つかりました。可能な限り回復しますか?ブックの発行元が信頼できる場合は、「はい」をクリックしてください。

と出ます。
回復を試みても何も編集されていない状態になります。
上記のプログラム実行時には何もエラーが出ていません。
おそらく保存する部分が上手くできていないのだと思われます。

###試したこと
変換元の画像が200枚ではファイルサイズが大きすぎるのではないかと思い、5枚でやってみたところ上手く保存できていました。
しかし、15枚ではうまく保存できていませんでした。
また、変換元の画像をさらにリサイズしたものでも上記と同じ結果となり、画像枚数が増えると保存ができていないようでした。

###補足情報
開発環境
-Windows10(64bit)
-Excel2016
-Python3.6.0(Anaconda4.4.0(64bit))
-Openpyxl2.5.0a3

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/09/11 03:13

画像サイズ(塗りつぶしたセルの数)が違っても、画像の枚数によってエラーが起きているっぽい、ということですね?Q.極めて小さい画像(10x10)でも同じことが起きるのでしょうか? ---エラーが出ない枚数ずつ連番か何かで出力して、VBAでガシャガシャくっつける解決策が見えたためです。
mdj

2017/09/11 07:35

1ファイルあたりのファイルサイズはどのくらいでしょうか。1ファイル50KB程度で同程度のピクセルサイズで処理をしましたが、32ファイル程度でも処理が完了しました。 [環境]Win10(64bit)/Python 3.5.2/Openpyxl2.3.2
退会済みユーザー

退会済みユーザー

2017/09/11 08:08

極めて小さい画像(12×7)200枚では保存に成功しました。また、(320×180)の画像では8枚までは正常に保存できましたが、9枚以降は保存に失敗しました。画像枚数ではなくファイルサイズに問題があるように思います。小分けに出力してからVBAでまとめる方法で解決できそうなので試してみます。画像のファイルサイズは1ファイル(320×180)で20KB程度です。
can110

2017/09/26 06:54

処理を見る限り、画像ファイル形式やサイズというより、縦×横サイズ×画像数→Fill対象の行列範囲=セル数に制限がありそうです。
mdj

2017/09/26 08:13

ちなみにですがメモリ(物理メモリ)はどの程度なのでしょうか。他のアプリケーションで大量に消費していて、この処理で足りなくなっているとかがあるのではないかなと。処理時にタスクマネージャーを表示しながら処理してみるのも一考かなと思い当りました
退会済みユーザー

退会済みユーザー

2017/09/26 09:18

プログラム実行時のメモリ消費は約30%でした。メモリは足りているように思います。
guest

回答2

0

ベストアンサー

回答ではありませんが、本質的にはセルに対するFill操作に対しての問題の有無だと思われるので、RGB値をダミー生成して試してみました。

Win10, Excel2007, Python 3.5.4 :: Anaconda custom (64-bit), openpyxl==2.4.8
で画像数15だとtest.xlsxのファイルサイズ 3.79MBで開けました。処理時間は約数分。

画像数200にすると時間がかかりすぎるので止めました。

検証コード

Python

1from string import ascii_uppercase as AtoZ 2from openpyxl import load_workbook 3from openpyxl.styles import PatternFill 4 5IMG_CNT = 15 # 画像の枚数 6IMG_W = 320 # 画像の幅 7IMG_H = 180 # 画像の高さ 8 9print('init') 10 11''' 12エクセルの初期設定 13ビットマップ化したものを各セルに塗りつぶすためにセルの形を変形 14''' 15 16# エクセルファイル読み込み 17wb = load_workbook(filename='./test.xlsx') 18# アクティブなシートを取り出す 19ws = wb.active 20 21# エクセルの列名リスト作成 22col_name = list(AtoZ) # 'A'~'Z' 23for i in range(IMG_W - 26): # 'AA'~ 24 col_name.append(AtoZ[i // 26] + AtoZ[i % 26]) 25 26for col in range(IMG_W): 27 # 列の幅を変更 28 ws.column_dimensions[col_name[col]].width = 0.3 29 30 for row in range(IMG_H * IMG_CNT): 31 # 行の高さを変更 32 ws.row_dimensions[row].height = 1.5 33 34 35''' 36各セルの塗りつぶし 37''' 38 39next_row = 0 40count = 0 41 42for i in range(IMG_CNT): 43 44 print('fill', i); 45 46 for row in range(IMG_H): 47 for col in range(IMG_W): 48 # 赤、緑、青の値を青、緑、赤の順に16進数2桁ずつの文字列へ変換 49 color = '%02x%02x%02x' % (row % 256, col % 256, row % 256) 50 51 # 塗りつぶすセル名を取得 52 cell_name = col_name[col] + str(row + 1 + next_row) 53 # セル名をセット 54 cell = ws[cell_name] 55 # 塗りつぶし 56 cell.fill = PatternFill(patternType='solid', fgColor=color) 57 58 count += 1 59 60 next_row = count 61 62wb.save('test.xlsx') 63print('done')

結果(Excel2007上で表示)
イメージ説明

投稿2017/09/26 07:16

編集2017/09/26 07:17
can110

総合スコア38266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/09/26 11:35

回答ありがとうございます。 検証コードを参考にいろいろ試してみたところ、読み込んだ画像を一度K平均法で32色に減色することで問題を解決することができました。 今回の問題を解決するにあたり、たくさんの方々にお世話になりました。この場を借りてお礼申し上げます。
can110

2017/09/26 12:26 編集

減色で解決ですか。なるほど。興味深いです。 セル数には関係なく、Fill色の種類(パターン)数に制限(限界)があるのかもしれませんね。 検証コードでも色を乱数で32bit全色を生成するとエラー再現するかもしれません。 いずれにせよ解決してよかったです。
退会済みユーザー

退会済みユーザー

2017/09/27 01:19

解決してよかったです。can110様、ありがとうございました。 ふと思ったのですが、Excelのバージョン表記に「(32bit)」と記入されていませんか? Excelの場合、2003以前のバージョンと互換性を保つ必要があること等から、 (32bit)となっていることが多いので…。 その場合は、R,G,Bとも0~255のパターンの組み合わせでしか、色の再現が 出来ないようになっています。 ちなみに、Excel(64bit)インストールは、副作用が大きいため避けたほうが無難です。
can110

2017/09/27 01:36

コメントありがとうございます。 32bit版のExcel2007にてtest.xlsxの作成および開いて表示させました。 ちなみに表示時のExcelウインドウタイトルには「互換モード」の表記はありませんでした。 たしかにExcel2000などの頃は色の制限が厳しかったような覚えがあります。 以下見る限り2007では1600万色で制限ないようですが、パターン数にはなんらか制限あるような気もします。 https://support.office.com/ja-jp/article/Excel-%E3%81%AE%E4%BB%95%E6%A7%98%E3%81%8A%E3%82%88%E3%81%B3%E5%88%B6%E9%99%90-1672b34d-7043-467e-8e27-269d656771c3#ID0EBABAAA=Excel_2007
退会済みユーザー

退会済みユーザー

2017/10/10 02:29

私の説明不足・確認不足がありました…。 もしかして、OSは「WindowsVista」の32bitでしょうか? Excel2007の場合、その可能性もあり得ますので…。 実は、WindowsVista+Excel2007の組み合わせは、MicroSoft社自体「忘れたいほどの失策」とも 言えるほどのものなので…。 OS・Excelとも「昔の遺産を出来るだけ引き継ぐ」+「スリープモードがデフォルト」という 思想のため、OSレベルからメモリを圧迫しやすく、意外にユーザー用のメモリ領域が狭いという 弱点があります(私も使用経験ありましたが、メモリ容量をユーザー側で監視しないと 不安になるほどでした…)。   このため、Excel2010以上のバージョンで「test.xlsx」を作成することを、「強くお勧め」します。 (出来ない場合は、申し訳ありません。お節介、という事で。)
guest

0

Excelでの画像関連のトラブルは、意外に多いですよ?

一応ご確認致したい事ですが…

  • 作成できたExcelファイルは20MB前後以上でしょうか?
  • 画像はJPEGの「標準」「高品質」のいずれかでしょうか?

私の経験では、JPEG「高品質」保存済みのファイルををそのまま貼り付け、Excelファイルが
約20MBオーバーだと、下記の現象が発生していました(参考:Excel2010です)。

  • ファイルが保存方法に関係なく保存不可能。
  • 開くときに同じようなメッセージが出て、開くこと自体が出来なくなる。

これらはExcel2003以前からずっと現時点まで解決されていない問題です…。

画像枚数というよりは、ファイルサイズの問題と考えられます。

解決策としては、
0. Excelの「ファイルタブ→オプション→詳細設定→イメージのサイズと画像」で、
dpiの数値を200より低くする(画像データが圧縮されてぼやけてしまう副作用あり)。
「復元用のデータを保存しない」にもチェックを入れる。
0. 画像ファイル自体の「余分な部分」を可能な限り「トリミング処理」してから処理を行なう。
0. 作成したExcelファイルが20MBを超えないようにする。

それ以外の方法につきましては、残念ですが思い当たりません…。
お力になれず大変申し訳ございませんが、他の方々でいい方法がご提案ございましたら、
そちらを実践された方がよろしいかと。

取り敢えず、私の方は何か解決の糸口になれれば、と思います…。

投稿2017/09/26 05:58

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/09/26 06:48

回答ありがとうございます。 作成されるExcelファイルは画像1ファイル(320×180)を8枚分で実行して6MB程度です。 JPEGの品質は標準です。 解決策を試してみましたが、同じ問題に直面してしまいました。 また、今回の場合、画像ファイルをExcelに直接貼り付けているのではなく、一度ビットマップ変換した後に各ピクセルに対応するセルの背景色を変更するようにしています。 そのため、別のアプローチが必要なのではないかと思っています。 いろいろ考えてはいるのですが、迷宮入りしそうです・・・。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問