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

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

ただいまの
回答率

88.62%

エクセルファイルからのデータの抽出

解決済

回答 1

投稿

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

Nyann

score 12

下記の異なるファイル名のエクセルファイルから必要な部分の情報を抜きだしたいです。数日前に異なるファイル名のファイルについて投稿しておりました。
実現したいこと・エクセルシート内の記載内容は同じです。過去の投稿で得たコードの修正点をご教示いただければと思います。よろしくお願い致します。

ファイル名①: 2017.6.6XXXX日報
ファイル名②: 2017.09.12XXXX日報
ファイル名③: 2017.06.06XXXX日報
ファイル名④: XXXX日報20140715

過去の投稿でのコード
---------------------------------------   
import glob
import locale
import os
import re
import time
from datetime import datetime

import openpyxl as xl

locale.setlocale(locale.LC_ALL, '')

 エクセルファイル一覧を取得する。

xlsx_files = os.path.join('日報', '*.xlsx')
xlsx_paths = [path for path in sorted(glob.glob(xlsx_files))]

out_wb = xl.Workbook()  # 新しい workbook を作成する。
out_ws = out_wb.active

row_offset = 1

 ヘッダー

headers = ['タイトル', '更新日時', 'B', 'C', 'D', 'E', 'F',
'G', 'H', 'I', 'J', 'K', 'L']
for c, label in enumerate(headers, 1):
out_ws.cell(row=row_offset, column=c).value = label
row_offset += 1

for path in xlsx_paths:
print('reading... ', path)

 更新日時を取得

datetime = datetime.fromtimestamp(os.path.getmtime(path))
modified = '{0:%Y年%m月%d日 %H時%M分}'.format(datetime)

 Excel ファイルを読み込む。

wb = xl.load_workbook(path, data_only=True)
ws = wb.active

 ファイル名から日付部分を取得

matches = re.search(r'日報(\d{1,2})\.(\d{1,2})', os.path.basename(path))
month, date = matches.groups()
title = '{}/{}'.format(month, date)

 値をコピー B14:L28

out_ws.cell(row=row_offset, column=1).value = title  # タイトル
out_ws.cell(row=row_offset, column=2).value = modified  # 修正日時
for r, rows in enumerate(ws['B14:L28']):  # B14 ~ L28 の値
for c, cell in enumerate(rows):
out_ws.cell(row=row_offset + r, column=3 + c).value  = cell.value
row_offset += 15

 値をコピー B34:L48

out_ws.cell(row=row_offset, column=1).value = title  # タイトル
out_ws.cell(row=row_offset, column=2).value = modified  # 修正日時
for r, row in enumerate(ws['B34:L48']):  # B34 ~ L48 の値
for c, cell in enumerate(row):
out_ws.cell(row=row_offset + r, column=3 + c).value  = cell.value
row_offset += 15

 保存する。

out_wb.save('output.xlsx')

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

 質問欄にコードを貼る方法について

コードを貼るときは、コードブロックで囲むようにしてください。
そうしないとインデントが崩れてしまいます。
質問欄はあとからでも編集できます。

イメージ説明

 ファイル名から日付の抽出

文字列から一部分を抽出する場合は「正規表現を作成する」問題に帰着します。
正規表現についてわからない場合は便利なので、勉強してみるとよいかと思います。

サルにもわかる正規表現入門

以下に質問欄にあるファイル名から正規表現で年月日を抽出して、文字列で返すサンプルコードを貼ります。

import re

def get_title(filename):
    # 「テキスト日報20140715」のパターンを抽出
    matches = re.match(r'^.+日報(\d{4})(\d{2})(\d{2})\.xlxs$', filename)
    if matches:
        year, month, date = matches.groups()
        return '{:0>4}/{:0>2}/{:0>2}'.format(year, month, date)

    # 「2017.6.6テキスト日報」のパターンを抽出
    matches = re.match(r'^(\d{4})\.(\d{1,})\.(\d{1,})[^\d].+日報\.xlxs$', filename)
    if matches:
        year, month, date = matches.groups()
        return '{:0>4}/{:0>2}/{:0>2}'.format(year, month, date)

    raise ValueError('Failed to parse specified string.')

# テスト (この部分はテスト用なのでコピペしなくていいです。)(
assert get_title('2017.6.6テキスト日報.xlxs') == '2017/06/06'
assert get_title('2017.09.12テキスト日報.xlxs') == '2017/09/12'
assert get_title('2017.06.06テキスト日報.xlxs') == '2017/06/06'
assert get_title('テキスト日報20140715.xlxs') == '2014/07/15'

以下の部分を変更して、使ってみてください。

変更前

matches = re.search(r'日報(\d{1,2})\.(\d{1,2})', os.path.basename(path))
month, date = matches.groups()
title = '{}/{}'.format(month, date)

変更後

title = get_title(os.path.basename(path))

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/10/15 18:48

    コードを張る際のアドバイス、正規表現に関するリンクありがとうございました。何ケースか見ることでだんだんコードの意味が理解出来始めました。ありがとうございます。

    キャンセル

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

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

関連した質問

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