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

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

ただいまの
回答率

90.61%

  • Python

    7475questions

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

  • Python 3.x

    5889questions

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

  • Excel

    1467questions

    Excelは、マイクロソフト社が開発しているデータ集計や分析を行う表計算ソフトの一つです。文書作成や表計算、資料作成などの多彩な機能を備えており、統合パッケージであるMicrosoft Officeに含まれています。

  • OpenCV

    1019questions

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

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,185

konnyaku256

score 4

状況・到達目標

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

該当のソースコード

# -*- coding:utf-8 -*-

import cv2
import glob
from string import ascii_uppercase as AtoZ
from openpyxl import load_workbook
from openpyxl.styles import PatternFill

image_path = '用意した画像の保存パス'
#用意した画像の枚数
number = 200

'''
エクセルの初期設定
ビットマップ化したものを各セルに塗りつぶすためにセルの形を変形
'''
image = cv2.imread(image_path + '0.jpg')

# エクセルファイル読み込み
wb = load_workbook(filename='test.xlsx')
# アクティブなシートを取り出す
ws = wb.active

# エクセルの列名リスト作成
col_name = list(AtoZ)                   # 'A'~'Z'
for i in range(len(image[0]) - 26):    # 'AA'~
  col_name.append(AtoZ[i // 26] + AtoZ[i % 26])

for col in range(len(image[0])):
  # 列の幅を変更
  ws.column_dimensions[col_name[col]].width = 0.3

  for row in range(len(image) * number):
    # 行の高さを変更
    ws.row_dimensions[row].height = 1.5


'''
各セルの塗りつぶし
'''
images = glob.glob(image_path + '*.jpg')

next_row = 0
count = 0

for img_path in images:
    image = cv2.imread(img_path)

    for row in range(len(image)):
      for col in range(len(image[row])):
        # 赤、緑、青の値を青、緑、赤の順に16進数2桁ずつの文字列へ変換
        red, green, blue = image[row][col]
        color = '%02x%02x%02x' % (blue, green, red)

        # 塗りつぶすセル名を取得
        cell_name = col_name[col] + str(row + 1 + next_row)
        # セル名をセット
        cell = ws[cell_name]
        # 塗りつぶし
        cell.fill = PatternFill(patternType='solid', fgColor=color)

      count += 1

    next_row = count

wb.save('test.xlsx')

発生している問題

保存されたExcelファイルを開こうとすると

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


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

試したこと

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

補足情報

開発環境
-Windows10(64bit)
-Excel2016
-Python3.6.0(Anaconda4.4.0(64bit))
-Openpyxl2.5.0a3

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • can110

    2017/09/26 15:54

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

    キャンセル

  • module_jung

    2017/09/26 17:13

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

    キャンセル

  • konnyaku256

    2017/09/26 18:18

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

    キャンセル

回答 2

checkベストアンサー

0

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

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

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

検証コード

from string import ascii_uppercase as AtoZ
from openpyxl import load_workbook
from openpyxl.styles import PatternFill

IMG_CNT = 15 # 画像の枚数
IMG_W = 320   # 画像の幅
IMG_H = 180   # 画像の高さ

print('init')

'''
エクセルの初期設定
ビットマップ化したものを各セルに塗りつぶすためにセルの形を変形
'''

# エクセルファイル読み込み
wb = load_workbook(filename='./test.xlsx')
# アクティブなシートを取り出す
ws = wb.active

# エクセルの列名リスト作成
col_name = list(AtoZ)          # 'A'~'Z'
for i in range(IMG_W - 26):    # 'AA'~
  col_name.append(AtoZ[i // 26] + AtoZ[i % 26])

for col in range(IMG_W):
  # 列の幅を変更
  ws.column_dimensions[col_name[col]].width = 0.3

  for row in range(IMG_H * IMG_CNT):
    # 行の高さを変更
    ws.row_dimensions[row].height = 1.5


'''
各セルの塗りつぶし
'''

next_row = 0
count = 0

for i in range(IMG_CNT):

    print('fill', i);

    for row in range(IMG_H):
      for col in range(IMG_W):
        # 赤、緑、青の値を青、緑、赤の順に16進数2桁ずつの文字列へ変換
        color = '%02x%02x%02x' % (row % 256, col % 256, row % 256)

        # 塗りつぶすセル名を取得
        cell_name = col_name[col] + str(row + 1 + next_row)
        # セル名をセット
        cell = ws[cell_name]
        # 塗りつぶし
        cell.fill = PatternFill(patternType='solid', fgColor=color)

      count += 1

    next_row = count

wb.save('test.xlsx')
print('done')

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

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/26 20:35

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

    キャンセル

  • 2017/09/26 21:24 編集

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

    キャンセル

  • 2017/09/27 10:19

    解決してよかったです。can110様、ありがとうございました。

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

    キャンセル

  • 2017/09/27 10: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 11:29

    私の説明不足・確認不足がありました…。
    もしかして、OSは「WindowsVista」の32bitでしょうか?
    Excel2007の場合、その可能性もあり得ますので…。

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

    キャンセル

0

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

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

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

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

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

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

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

解決策としては、

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

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

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

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/26 15:48

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

    キャンセル

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

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

関連した質問

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

  • Python

    7475questions

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

  • Python 3.x

    5889questions

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

  • Excel

    1467questions

    Excelは、マイクロソフト社が開発しているデータ集計や分析を行う表計算ソフトの一つです。文書作成や表計算、資料作成などの多彩な機能を備えており、統合パッケージであるMicrosoft Officeに含まれています。

  • OpenCV

    1019questions

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