import os
import datetime
import pandas as pd
from openpyxl import load_workbook
# --- БЛОК НАСТРОЕК (РЕДАКТИРОВАТЬ ЗДЕСЬ) ---
# Папка с файлами
INPUT_FOLDER = 'reports'
# Имя итогового файла
OUTPUT_FILE = 'rezultat.xlsx'
# Название листа в Excel, откуда брать данные (как на скрине)
SHEET_NAME = 'Баллы'
# СЛОВАРЬ: "Название колонки в итоговом файле": "Адрес ячейки"
# Добавляйте сюда сколько угодно строк
CELLS_CONFIG = {
"ГП_Вырубной_2500": "B13",
"ГП_Вырубной_1000": "C13",
"ГП_Вырубной_500": "D13",
"ГП_Вырубной_Сумма": "E13",
"Итого_Сумма": "E46",
# "Пример_Своего_Поля": "K15",
}
# -------------------------------------------
def process_files():
data_list = []
files = [f for f in os.listdir(INPUT_FOLDER) if f.endswith(('.xlsx', '.xlsm'))]
total_files = len(files)
print(f"Найдено файлов: {total_files}. Начинаю обработку...")
for index, filename in enumerate(files, 1):
filepath = os.path.join(INPUT_FOLDER, filename)
# Получаем метаданные файла
# Имя файла без расширения (считаем, что это ФИО)
fio = os.path.splitext(filename)[0]
# Дата модификации
mod_time = os.path.getmtime(filepath)
date_file = datetime.datetime.fromtimestamp(mod_time).strftime('%Y-%m-%d %H:%M:%S')
row_data = {
"ФИО": fio,
"Дата файл": date_file
}
try:
# data_only=True важно, чтобы выгружались числа, а не формулы
wb = load_workbook(filepath, data_only=True, read_only=True)
if SHEET_NAME in wb.sheetnames:
ws = wb[SHEET_NAME]
# Пробегаем по вашему словарю настроек
for col_name, cell_addr in CELLS_CONFIG.items():
try:
val = ws[cell_addr].value
row_data[col_name] = val
except:
row_data[col_name] = None
else:
print(f"⚠️ Лист '{SHEET_NAME}' не найден в файле {filename}")
wb.close()
data_list.append(row_data)
except Exception as e:
print(f"❌ Ошибка чтения {filename}: {e}")
# Вывод прогресса каждые 100 файлов
if index % 100 == 0:
print(f"Обработано {index} из {total_files}...")
# Сохранение
print("Формирую Excel...")
df = pd.DataFrame(data_list)
# Упорядочиваем колонки: сначала ФИО и Дата, потом те, что вы указали
cols = ["ФИО", "Дата файл"] + list(CELLS_CONFIG.keys())
df = df[cols]
df.to_excel(OUTPUT_FILE, index=False)
print(f"Готово! Файл сохранен как {OUTPUT_FILE}")
if name == "main":
process_files()
import datetime
import pandas as pd
from openpyxl import load_workbook
# --- БЛОК НАСТРОЕК (РЕДАКТИРОВАТЬ ЗДЕСЬ) ---
# Папка с файлами
INPUT_FOLDER = 'reports'
# Имя итогового файла
OUTPUT_FILE = 'rezultat.xlsx'
# Название листа в Excel, откуда брать данные (как на скрине)
SHEET_NAME = 'Баллы'
# СЛОВАРЬ: "Название колонки в итоговом файле": "Адрес ячейки"
# Добавляйте сюда сколько угодно строк
CELLS_CONFIG = {
"ГП_Вырубной_2500": "B13",
"ГП_Вырубной_1000": "C13",
"ГП_Вырубной_500": "D13",
"ГП_Вырубной_Сумма": "E13",
"Итого_Сумма": "E46",
# "Пример_Своего_Поля": "K15",
}
# -------------------------------------------
def process_files():
data_list = []
files = [f for f in os.listdir(INPUT_FOLDER) if f.endswith(('.xlsx', '.xlsm'))]
total_files = len(files)
print(f"Найдено файлов: {total_files}. Начинаю обработку...")
for index, filename in enumerate(files, 1):
filepath = os.path.join(INPUT_FOLDER, filename)
# Получаем метаданные файла
# Имя файла без расширения (считаем, что это ФИО)
fio = os.path.splitext(filename)[0]
# Дата модификации
mod_time = os.path.getmtime(filepath)
date_file = datetime.datetime.fromtimestamp(mod_time).strftime('%Y-%m-%d %H:%M:%S')
row_data = {
"ФИО": fio,
"Дата файл": date_file
}
try:
# data_only=True важно, чтобы выгружались числа, а не формулы
wb = load_workbook(filepath, data_only=True, read_only=True)
if SHEET_NAME in wb.sheetnames:
ws = wb[SHEET_NAME]
# Пробегаем по вашему словарю настроек
for col_name, cell_addr in CELLS_CONFIG.items():
try:
val = ws[cell_addr].value
row_data[col_name] = val
except:
row_data[col_name] = None
else:
print(f"⚠️ Лист '{SHEET_NAME}' не найден в файле {filename}")
wb.close()
data_list.append(row_data)
except Exception as e:
print(f"❌ Ошибка чтения {filename}: {e}")
# Вывод прогресса каждые 100 файлов
if index % 100 == 0:
print(f"Обработано {index} из {total_files}...")
# Сохранение
print("Формирую Excel...")
df = pd.DataFrame(data_list)
# Упорядочиваем колонки: сначала ФИО и Дата, потом те, что вы указали
cols = ["ФИО", "Дата файл"] + list(CELLS_CONFIG.keys())
df = df[cols]
df.to_excel(OUTPUT_FILE, index=False)
print(f"Готово! Файл сохранен как {OUTPUT_FILE}")
if name == "main":
process_files()
import os
# Впишите сюда имя папки или путь, как в скрипте
target_folder = 'reports'
print(f"--- ДИАГНОСТИКА ---")
print(f"Рабочая папка скрипта сейчас: {os.getcwd()}")
if os.path.exists(target_folder):
print(f"Папка '{target_folder}' найдена.")
files = os.listdir(target_folder)
xlsx_files = [f for f in files if f.endswith(('.xlsx', '.xlsm'))]
print(f"Всего файлов в папке: {len(files)}")
print(f"Подходящих Excel файлов: {len(xlsx_files)}")
if len(xlsx_files) == 0:
print("ОШИБКА: В папке нет файлов .xlsx! Проверьте расширение (может у вас .xls?)")
else:
print(f"ОШИБКА: Папка '{target_folder}' не найдена.")
print("Совет: Используйте полный путь (например: r'C:\MyWork\reports')")
# Впишите сюда имя папки или путь, как в скрипте
target_folder = 'reports'
print(f"--- ДИАГНОСТИКА ---")
print(f"Рабочая папка скрипта сейчас: {os.getcwd()}")
if os.path.exists(target_folder):
print(f"Папка '{target_folder}' найдена.")
files = os.listdir(target_folder)
xlsx_files = [f for f in files if f.endswith(('.xlsx', '.xlsm'))]
print(f"Всего файлов в папке: {len(files)}")
print(f"Подходящих Excel файлов: {len(xlsx_files)}")
if len(xlsx_files) == 0:
print("ОШИБКА: В папке нет файлов .xlsx! Проверьте расширение (может у вас .xls?)")
else:
print(f"ОШИБКА: Папка '{target_folder}' не найдена.")
print("Совет: Используйте полный путь (например: r'C:\MyWork\reports')")
import os
import datetime
import pandas as pd
from openpyxl import load_workbook
# --- БЛОК НАСТРОЕК ---
INPUT_FOLDER = r'reports' # Укажите путь к главной папке
OUTPUT_FILE = 'rezultat_v2.xlsx'
SHEET_NAME = 'Баллы'
# Ваши ячейки
CELLS_CONFIG = {
"ГП_Вырубной_2500": "B13",
"ГП_Вырубной_1000": "C13",
"ГП_Вырубной_500": "D13",
"ГП_Вырубной_Сумма": "E13",
"Итого_Сумма": "E46",
}
# ---------------------
def process_files():
data_list = []
count = 0
print(f"Начинаю поиск файлов в '{INPUT_FOLDER}' и всех подпапках...")
# os.walk проходит по всем вложенным папкам
for root, dirs, files in os.walk(INPUT_FOLDER):
for filename in files:
if filename.endswith(('.xlsx', '.xlsm')) and not filename.startswith('~$'):
# Полный путь формируется из текущей папки (root) и имени файла
filepath = os.path.join(root, filename)
count += 1
# Данные о файле
fio = os.path.splitext(filename)[0]
try:
mod_time = os.path.getmtime(filepath)
date_file = datetime.datetime.fromtimestamp(mod_time).strftime('%Y-%m-%d %H:%M:%S')
except:
date_file = "Ошибка даты"
row_data = {"ФИО": fio, "Дата файл": date_file}
# Чтение Excel
try:
wb = load_workbook(filepath, data_only=True, read_only=True)
if SHEET_NAME in wb.sheetnames:
ws = wb[SHEET_NAME]
for col_name, cell_addr in CELLS_CONFIG.items():
try:
val = ws[cell_addr].value
row_data[col_name] = val
except:
row_data[col_name] = None
wb.close()
data_list.append(row_data)
except Exception as e:
print(f"❌ Ошибка чтения {filename}: {e}")
if count % 100 == 0:
print(f"Обработано {count} файлов...")
if count == 0:
print("Файлы не найдены. Проверьте путь к папке.")
return
# Сохранение
print(f"Всего обработано {count} файлов. Формирую Excel...")
df = pd.DataFrame(data_list)
cols = ["ФИО", "Дата файл"] + list(CELLS_CONFIG.keys())
# Проверка на случай, если какие-то колонки пустые
existing_cols = [c for c in cols if c in df.columns]
df = df[existing_cols]
df.to_excel(OUTPUT_FILE, index=False)
print(f"Готово! Файл сохранен: {OUTPUT_FILE}")
if name == "main":
process_files()
import datetime
import pandas as pd
from openpyxl import load_workbook
# --- БЛОК НАСТРОЕК ---
INPUT_FOLDER = r'reports' # Укажите путь к главной папке
OUTPUT_FILE = 'rezultat_v2.xlsx'
SHEET_NAME = 'Баллы'
# Ваши ячейки
CELLS_CONFIG = {
"ГП_Вырубной_2500": "B13",
"ГП_Вырубной_1000": "C13",
"ГП_Вырубной_500": "D13",
"ГП_Вырубной_Сумма": "E13",
"Итого_Сумма": "E46",
}
# ---------------------
def process_files():
data_list = []
count = 0
print(f"Начинаю поиск файлов в '{INPUT_FOLDER}' и всех подпапках...")
# os.walk проходит по всем вложенным папкам
for root, dirs, files in os.walk(INPUT_FOLDER):
for filename in files:
if filename.endswith(('.xlsx', '.xlsm')) and not filename.startswith('~$'):
# Полный путь формируется из текущей папки (root) и имени файла
filepath = os.path.join(root, filename)
count += 1
# Данные о файле
fio = os.path.splitext(filename)[0]
try:
mod_time = os.path.getmtime(filepath)
date_file = datetime.datetime.fromtimestamp(mod_time).strftime('%Y-%m-%d %H:%M:%S')
except:
date_file = "Ошибка даты"
row_data = {"ФИО": fio, "Дата файл": date_file}
# Чтение Excel
try:
wb = load_workbook(filepath, data_only=True, read_only=True)
if SHEET_NAME in wb.sheetnames:
ws = wb[SHEET_NAME]
for col_name, cell_addr in CELLS_CONFIG.items():
try:
val = ws[cell_addr].value
row_data[col_name] = val
except:
row_data[col_name] = None
wb.close()
data_list.append(row_data)
except Exception as e:
print(f"❌ Ошибка чтения {filename}: {e}")
if count % 100 == 0:
print(f"Обработано {count} файлов...")
if count == 0:
print("Файлы не найдены. Проверьте путь к папке.")
return
# Сохранение
print(f"Всего обработано {count} файлов. Формирую Excel...")
df = pd.DataFrame(data_list)
cols = ["ФИО", "Дата файл"] + list(CELLS_CONFIG.keys())
# Проверка на случай, если какие-то колонки пустые
existing_cols = [c for c in cols if c in df.columns]
df = df[existing_cols]
df.to_excel(OUTPUT_FILE, index=False)
print(f"Готово! Файл сохранен: {OUTPUT_FILE}")
if name == "main":
process_files()
import os
# ВСТАВЬТЕ СЮДА ВАШ ПОЛНЫЙ ПУТЬ
INPUT_FOLDER = r'C:\СЮДА_ВСТАВИТЬ_ПОЛНЫЙ_ПУТЬ'
print(f"--- ДИАГНОСТИКА ---")
print(f"Ищем в папке: {os.path.abspath(INPUT_FOLDER)}")
if os.path.exists(INPUT_FOLDER):
print("✅ Папка найдена. Сканируем содержимое...")
count = 0
found_excel = 0
for root, dirs, files in os.walk(INPUT_FOLDER):
for filename in files:
count += 1
# Показываем первые 5 любых файлов, чтобы понять, что там лежит
if count <= 5:
print(f" Вижу файл: {filename}")
if filename.endswith(('.xlsx', '.xlsm')):
found_excel += 1
print("-" * 20)
print(f"Всего файлов: {count}")
print(f"Подходящих Excel (.xlsx/.xlsm): {found_excel}")
if found_excel == 0:
print("❌ ОШИБКА: Excel файлы не найдены! Проверьте расширения.")
else:
print("✅ Файлы есть. Проблема была в основном скрипте (возможно, путь).")
else:
print("❌ ОШИБКА: Папка по этому пути НЕ существует.")
# ВСТАВЬТЕ СЮДА ВАШ ПОЛНЫЙ ПУТЬ
INPUT_FOLDER = r'C:\СЮДА_ВСТАВИТЬ_ПОЛНЫЙ_ПУТЬ'
print(f"--- ДИАГНОСТИКА ---")
print(f"Ищем в папке: {os.path.abspath(INPUT_FOLDER)}")
if os.path.exists(INPUT_FOLDER):
print("✅ Папка найдена. Сканируем содержимое...")
count = 0
found_excel = 0
for root, dirs, files in os.walk(INPUT_FOLDER):
for filename in files:
count += 1
# Показываем первые 5 любых файлов, чтобы понять, что там лежит
if count <= 5:
print(f" Вижу файл: {filename}")
if filename.endswith(('.xlsx', '.xlsm')):
found_excel += 1
print("-" * 20)
print(f"Всего файлов: {count}")
print(f"Подходящих Excel (.xlsx/.xlsm): {found_excel}")
if found_excel == 0:
print("❌ ОШИБКА: Excel файлы не найдены! Проверьте расширения.")
else:
print("✅ Файлы есть. Проблема была в основном скрипте (возможно, путь).")
else:
print("❌ ОШИБКА: Папка по этому пути НЕ существует.")
# ... примерно строка 40 в функции process_files ...
# Чтение Excel
try:
wb = load_workbook(filepath, data_only=True, read_only=True)
# --- НОВЫЙ ДИАГНОСТИЧЕСКИЙ БЛОК ---
sheetnames = wb.sheetnames
if SHEET_NAME not in sheetnames:
print(f"⚠️ Файл {filename}: Лист '{SHEET_NAME}' не найден.")
print(f" Доступные листы: {sheetnames}") # <-- ЭТА СТРОКА ОЧЕНЬ ВАЖНА
wb.close()
continue # Переходим к следующему файлу
# ----------------------------------
if SHEET_NAME in wb.sheetnames:
ws = wb[SHEET_NAME]
# ... остальной код ...
# Чтение Excel
try:
wb = load_workbook(filepath, data_only=True, read_only=True)
# --- НОВЫЙ ДИАГНОСТИЧЕСКИЙ БЛОК ---
sheetnames = wb.sheetnames
if SHEET_NAME not in sheetnames:
print(f"⚠️ Файл {filename}: Лист '{SHEET_NAME}' не найден.")
print(f" Доступные листы: {sheetnames}") # <-- ЭТА СТРОКА ОЧЕНЬ ВАЖНА
wb.close()
continue # Переходим к следующему файлу
# ----------------------------------
if SHEET_NAME in wb.sheetnames:
ws = wb[SHEET_NAME]
# ... остальной код ...
# --- ВНУТРИ ФУНКЦИИ process_files, НАЧИНАЯ СО СТРОКИ 40 ---
# Чтение Excel
try:
# 1. ПРОВЕРКА ЗАГРУЗКИ
print(f" [DEBUG-1] Загрузка: {filename}...")
wb = load_workbook(filepath, data_only=True, read_only=True)
sheetnames = wb.sheetnames
if SHEET_NAME not in sheetnames:
print(f" [DEBUG-2] ❌ ОШИБКА: Лист '{SHEET_NAME}' не найден. Доступные листы: {sheetnames}")
wb.close()
continue
ws = wb[SHEET_NAME]
# Сбор данных (ОСТАВЬТЕ ВАШУ ЛОГИКУ СБОРА ЯЧЕЕК ЗДЕСЬ)
for col_name, cell_addr in CELLS_CONFIG.items():
# Ваша логика сбора ячеек...
val = ws[cell_addr].value
row_data[col_name] = val
data_list.append(row_data)
# 2. ПРОВЕРКА ДОБАВЛЕНИЯ
print(f" [DEBUG-3] ✅ Файл {filename} успешно обработан и ДОБАВЛЕН в список.")
wb.close()
except Exception as e:
print(f"❌ КРИТИЧЕСКАЯ ОШИБКА при чтении {filename}: {e}")
if count % 100 == 0:
print(f"Обработано {count} файлов...")
# -------------------------------------------------------------
# Чтение Excel
try:
# 1. ПРОВЕРКА ЗАГРУЗКИ
print(f" [DEBUG-1] Загрузка: {filename}...")
wb = load_workbook(filepath, data_only=True, read_only=True)
sheetnames = wb.sheetnames
if SHEET_NAME not in sheetnames:
print(f" [DEBUG-2] ❌ ОШИБКА: Лист '{SHEET_NAME}' не найден. Доступные листы: {sheetnames}")
wb.close()
continue
ws = wb[SHEET_NAME]
# Сбор данных (ОСТАВЬТЕ ВАШУ ЛОГИКУ СБОРА ЯЧЕЕК ЗДЕСЬ)
for col_name, cell_addr in CELLS_CONFIG.items():
# Ваша логика сбора ячеек...
val = ws[cell_addr].value
row_data[col_name] = val
data_list.append(row_data)
# 2. ПРОВЕРКА ДОБАВЛЕНИЯ
print(f" [DEBUG-3] ✅ Файл {filename} успешно обработан и ДОБАВЛЕН в список.")
wb.close()
except Exception as e:
print(f"❌ КРИТИЧЕСКАЯ ОШИБКА при чтении {filename}: {e}")
if count % 100 == 0:
print(f"Обработано {count} файлов...")
# -------------------------------------------------------------
# ... весь код и функция process_files выше ...
if name == "main":
print("--- 🟢 ПОПЫТКА ВЫЗОВА ФУНКЦИИ ---")
process_files()
print("--- 🔵 КОНЕЦ ВЫЗОВА ФУНКЦИИ ---")
if name == "main":
print("--- 🟢 ПОПЫТКА ВЫЗОВА ФУНКЦИИ ---")
process_files()
print("--- 🔵 КОНЕЦ ВЫЗОВА ФУНКЦИИ ---")
import os
import datetime
import pandas as pd
from openpyxl import load_workbook
# ==========================
# КОНФИГУРАЦИЯ
# ==========================
INPUT_FOLDER = r"PATH_TO_FOLDER" # корневая папка для поиска Excel-файлов
OUTPUT_FILE = "result.xlsx" # итоговый файл
SHEET_NAME = "Баллы" # лист для чтения
CELLS_CONFIG = { # колонка -> адрес ячейки
"Итого_Сумма": "E46",
"Пример": "C10"
}
# ==========================
def get_file_modified_datetime(path: str) -> str:
timestamp = os.path.getmtime(path)
dt = datetime.datetime.fromtimestamp(timestamp)
return dt.strftime("%Y-%m-%d %H:%M:%S")
def process_excel_file(filepath: str) -> dict | None:
"""Читает данные из Excel-файла и возвращает словарь со значениями."""
try:
wb = load_workbook(filepath, read_only=True, data_only=True)
except Exception as e:
print(f"[ОШИБКА] Не удалось открыть файл: {filepath} — {e}")
return None
if SHEET_NAME not in wb.sheetnames:
print(f"[ПРОПУСК] Нет листа '{SHEET_NAME}' в файле: {filepath}")
return None
ws = wb[SHEET_NAME]
row = {}
# имя файла без расширения
row["ФИО"] = os.path.splitext(os.path.basename(filepath))[0]
# дата модификации
row["Дата_файла"] = get_file_modified_datetime(filepath)
# значения из ячеек
for col_name, cell_addr in CELLS_CONFIG.items():
try:
value = ws[cell_addr].value
except Exception:
value = None
row[col_name] = value
return row
def main():
results = []
processed_count = 0
for root, dirs, files in os.walk(INPUT_FOLDER):
for file in files:
if not (file.endswith(".xlsx") or file.endswith(".xlsm")):
continue
if file.startswith("~$"):
continue # игнорируем временные файлы
full_path = os.path.join(root, file)
processed_count += 1
if processed_count % 100 == 0:
print(f"[ПРОГРЕСС] Обработано файлов: {processed_count}")
row = process_excel_file(full_path)
if row:
results.append(row)
if not results:
print("[ГОТОВО] Нет данных для сохранения.")
return
df = pd.DataFrame(results)
df.to_excel(OUTPUT_FILE, index=False)
print(f"[ГОТОВО] Сохранено строк: {len(df)}")
print(f"[ГОТОВО] Итоговый файл: {OUTPUT_FILE}")
if name == "main":
main()
import datetime
import pandas as pd
from openpyxl import load_workbook
# ==========================
# КОНФИГУРАЦИЯ
# ==========================
INPUT_FOLDER = r"PATH_TO_FOLDER" # корневая папка для поиска Excel-файлов
OUTPUT_FILE = "result.xlsx" # итоговый файл
SHEET_NAME = "Баллы" # лист для чтения
CELLS_CONFIG = { # колонка -> адрес ячейки
"Итого_Сумма": "E46",
"Пример": "C10"
}
# ==========================
def get_file_modified_datetime(path: str) -> str:
timestamp = os.path.getmtime(path)
dt = datetime.datetime.fromtimestamp(timestamp)
return dt.strftime("%Y-%m-%d %H:%M:%S")
def process_excel_file(filepath: str) -> dict | None:
"""Читает данные из Excel-файла и возвращает словарь со значениями."""
try:
wb = load_workbook(filepath, read_only=True, data_only=True)
except Exception as e:
print(f"[ОШИБКА] Не удалось открыть файл: {filepath} — {e}")
return None
if SHEET_NAME not in wb.sheetnames:
print(f"[ПРОПУСК] Нет листа '{SHEET_NAME}' в файле: {filepath}")
return None
ws = wb[SHEET_NAME]
row = {}
# имя файла без расширения
row["ФИО"] = os.path.splitext(os.path.basename(filepath))[0]
# дата модификации
row["Дата_файла"] = get_file_modified_datetime(filepath)
# значения из ячеек
for col_name, cell_addr in CELLS_CONFIG.items():
try:
value = ws[cell_addr].value
except Exception:
value = None
row[col_name] = value
return row
def main():
results = []
processed_count = 0
for root, dirs, files in os.walk(INPUT_FOLDER):
for file in files:
if not (file.endswith(".xlsx") or file.endswith(".xlsm")):
continue
if file.startswith("~$"):
continue # игнорируем временные файлы
full_path = os.path.join(root, file)
processed_count += 1
if processed_count % 100 == 0:
print(f"[ПРОГРЕСС] Обработано файлов: {processed_count}")
row = process_excel_file(full_path)
if row:
results.append(row)
if not results:
print("[ГОТОВО] Нет данных для сохранения.")
return
df = pd.DataFrame(results)
df.to_excel(OUTPUT_FILE, index=False)
print(f"[ГОТОВО] Сохранено строк: {len(df)}")
print(f"[ГОТОВО] Итоговый файл: {OUTPUT_FILE}")
if name == "main":
main()
import os
import datetime
import pandas as pd
from openpyxl import load_workbook
# ==========================
# КОНФИГУРАЦИЯ
# ==========================
INPUT_FOLDER = r"PATH_TO_FOLDER"
OUTPUT_FILE = "result.xlsx"
SHEET_NAME = "Баллы"
CELLS_CONFIG = {
"Итого_Сумма": "E46",
"Пример": "C10"
}
# ==========================
def get_file_modified_datetime(path: str) -> str:
timestamp = os.path.getmtime(path)
dt = datetime.datetime.fromtimestamp(timestamp)
return dt.strftime("%Y-%m-%d %H:%M:%S")
def process_excel_file(filepath: str) -> dict | None:
try:
wb = load_workbook(filepath, read_only=True, data_only=True)
except Exception as e:
print(f"[ОШИБКА] Не удалось открыть: {filepath} — {e}")
return None
if SHEET_NAME not in wb.sheetnames:
print(f"[ПРОПУСК] Нет листа '{SHEET_NAME}' → {filepath}")
return None
ws = wb[SHEET_NAME]
row = {
"ФИО": os.path.splitext(os.path.basename(filepath))[0],
"Дата_файла": get_file_modified_datetime(filepath),
}
for col_name, cell_addr in CELLS_CONFIG.items():
try:
row[col_name] = ws[cell_addr].value
except Exception:
row[col_name] = None
return row
def main():
results = []
all_found = 0
print(f"Ищу файлы в: {INPUT_FOLDER}\n")
for root, dirs, files in os.walk(INPUT_FOLDER):
for file in files:
if not (file.endswith(".xlsx") or file.endswith(".xlsm")):
continue
if file.startswith("~$"):
continue
full_path = os.path.join(root, file)
all_found += 1
print(f"[Найден файл] {full_path}")
row = process_excel_file(full_path)
if row:
print(f" → Добавлен")
results.append(row)
else:
print(f" → Пропущен")
print("\nВсего Excel-файлов найдено:", all_found)
print("Успешно обработано:", len(results))
df = pd.DataFrame(results)
df.to_excel(OUTPUT_FILE, index=False)
print(f"\n[ГОТОВО] Итоговый файл создан: {OUTPUT_FILE}")
if name == "main":
main()
import datetime
import pandas as pd
from openpyxl import load_workbook
# ==========================
# КОНФИГУРАЦИЯ
# ==========================
INPUT_FOLDER = r"PATH_TO_FOLDER"
OUTPUT_FILE = "result.xlsx"
SHEET_NAME = "Баллы"
CELLS_CONFIG = {
"Итого_Сумма": "E46",
"Пример": "C10"
}
# ==========================
def get_file_modified_datetime(path: str) -> str:
timestamp = os.path.getmtime(path)
dt = datetime.datetime.fromtimestamp(timestamp)
return dt.strftime("%Y-%m-%d %H:%M:%S")
def process_excel_file(filepath: str) -> dict | None:
try:
wb = load_workbook(filepath, read_only=True, data_only=True)
except Exception as e:
print(f"[ОШИБКА] Не удалось открыть: {filepath} — {e}")
return None
if SHEET_NAME not in wb.sheetnames:
print(f"[ПРОПУСК] Нет листа '{SHEET_NAME}' → {filepath}")
return None
ws = wb[SHEET_NAME]
row = {
"ФИО": os.path.splitext(os.path.basename(filepath))[0],
"Дата_файла": get_file_modified_datetime(filepath),
}
for col_name, cell_addr in CELLS_CONFIG.items():
try:
row[col_name] = ws[cell_addr].value
except Exception:
row[col_name] = None
return row
def main():
results = []
all_found = 0
print(f"Ищу файлы в: {INPUT_FOLDER}\n")
for root, dirs, files in os.walk(INPUT_FOLDER):
for file in files:
if not (file.endswith(".xlsx") or file.endswith(".xlsm")):
continue
if file.startswith("~$"):
continue
full_path = os.path.join(root, file)
all_found += 1
print(f"[Найден файл] {full_path}")
row = process_excel_file(full_path)
if row:
print(f" → Добавлен")
results.append(row)
else:
print(f" → Пропущен")
print("\nВсего Excel-файлов найдено:", all_found)
print("Успешно обработано:", len(results))
df = pd.DataFrame(results)
df.to_excel(OUTPUT_FILE, index=False)
print(f"\n[ГОТОВО] Итоговый файл создан: {OUTPUT_FILE}")
if name == "main":
main()
#!/usr/bin/env python3
# debug_excel_collector.py
import os
import sys
import datetime
import traceback
from pathlib import Path
import pandas as pd
from openpyxl import load_workbook
# ==========================
# КОНФИГУРАЦИЯ
# ==========================
# Установи тут корректный путь к папке с файлами
INPUT_FOLDER = r"PATH_TO_FOLDER" # <-- замените на ваш путь
OUTPUT_FILE = "result.xlsx"
OUTPUT_CSV = "result.csv"
SHEET_NAME = "Баллы"
CELLS_CONFIG = {
"Итого_Сумма": "E46",
"Пример": "C10"
}
LOG_FILE = "debug_log.txt"
# ==========================
def log(msg: str, *, end="\n"):
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
line = f"[{timestamp}] {msg}"
print(line, end=end)
try:
with open(LOG_FILE, "a", encoding="utf-8") as f:
f.write(line + ("\n" if end == "\n" else ""))
except Exception:
# best-effort logging; avoid infinite recursion if logging fails
print(f"[{timestamp}] [LOG ERROR] Не удалось записать в {LOG_FILE}")
def safe_str(x):
try:
return "" if x is None else str(x)
except Exception:
return "<non-stringable>"
def get_file_modified_datetime(path: Path) -> str:
try:
ts = path.stat().st_mtime
return datetime.datetime.fromtimestamp(ts).strftime("%Y-%m-%d %H:%M:%S")
except Exception:
return ""
def ensure_log_header():
try:
with open(LOG_FILE, "w", encoding="utf-8") as f:
f.write("Debug log for excel collector\n")
f.write(f"Start: {datetime.datetime.now().isoformat()}\n\n")
except Exception:
print("Не удалось создать лог-файл в текущей директории.")
def check_write_permission(path: Path) -> bool:
try:
test = path / ".write_test_tmp"
with open(test, "w", encoding="utf-8") as f:
f.write("test")
test.unlink()
return True
except Exception as e:
log(f"[ПРАВА] Нет прав на запись в папку {path}: {e}")
return False
def process_with_openpyxl(filepath: Path):
try:
wb = load_workbook(str(filepath), read_only=True, data_only=True)
except Exception as e:
log(f"[openpyxl] Ошибка открытия файла {filepath}: {e}")
return None, f"openpyxl_open_error: {safe_str(e)}"
try:
if SHEET_NAME not in wb.sheetnames:
wb.close()
return None, "missing_sheet"
ws = wb[SHEET_NAME]
except Exception as e:
try:
wb.close()
except Exception:
pass
log(f"[openpyxl] Ошибка доступа к листу в {filepath}: {e}")
return None, f"openpyxl_sheet_error: {safe_str(e)}"
row = {
"ФИО": filepath.stem,
"Дата_файла": get_file_modified_datetime(filepath)
}
for col_name, cell_addr in CELLS_CONFIG.items():
try:
# ws[cell_addr] may raise if address invalid
value = ws[cell_addr].value
except Exception as e:
value = None
log(f" [openpyxl] Не удалось прочитать ячейку {cell_addr} в {filepath}: {e}")
row[col_name] = value
try:
wb.close()
except Exception:
pass
return row, "ok"
def process_with_pandas(filepath: Path):
# fallback: pandas.read_excel (may evaluate formulas differently, but we try)
try:
# engine openpyxl recommended
df = pd.read_excel(filepath, sheet_name=SHEET_NAME, engine="openpyxl", nrows=0)
except Exception as e:
log(f"[pandas] Не удалось открыть/прочитать {filepath} через pandas: {e}")
return None, f"pandas_error: {safe_str(e)}"
# если чтение прошло, попробуем читать нужные ячейки через pandas by using header=None and usecols?
# Но pandas не читает одиночные адреса легко; поэтому — пробуем прочитать целый лист и взять нужные ячейки по адресам.
# debug_excel_collector.py
import os
import sys
import datetime
import traceback
from pathlib import Path
import pandas as pd
from openpyxl import load_workbook
# ==========================
# КОНФИГУРАЦИЯ
# ==========================
# Установи тут корректный путь к папке с файлами
INPUT_FOLDER = r"PATH_TO_FOLDER" # <-- замените на ваш путь
OUTPUT_FILE = "result.xlsx"
OUTPUT_CSV = "result.csv"
SHEET_NAME = "Баллы"
CELLS_CONFIG = {
"Итого_Сумма": "E46",
"Пример": "C10"
}
LOG_FILE = "debug_log.txt"
# ==========================
def log(msg: str, *, end="\n"):
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
line = f"[{timestamp}] {msg}"
print(line, end=end)
try:
with open(LOG_FILE, "a", encoding="utf-8") as f:
f.write(line + ("\n" if end == "\n" else ""))
except Exception:
# best-effort logging; avoid infinite recursion if logging fails
print(f"[{timestamp}] [LOG ERROR] Не удалось записать в {LOG_FILE}")
def safe_str(x):
try:
return "" if x is None else str(x)
except Exception:
return "<non-stringable>"
def get_file_modified_datetime(path: Path) -> str:
try:
ts = path.stat().st_mtime
return datetime.datetime.fromtimestamp(ts).strftime("%Y-%m-%d %H:%M:%S")
except Exception:
return ""
def ensure_log_header():
try:
with open(LOG_FILE, "w", encoding="utf-8") as f:
f.write("Debug log for excel collector\n")
f.write(f"Start: {datetime.datetime.now().isoformat()}\n\n")
except Exception:
print("Не удалось создать лог-файл в текущей директории.")
def check_write_permission(path: Path) -> bool:
try:
test = path / ".write_test_tmp"
with open(test, "w", encoding="utf-8") as f:
f.write("test")
test.unlink()
return True
except Exception as e:
log(f"[ПРАВА] Нет прав на запись в папку {path}: {e}")
return False
def process_with_openpyxl(filepath: Path):
try:
wb = load_workbook(str(filepath), read_only=True, data_only=True)
except Exception as e:
log(f"[openpyxl] Ошибка открытия файла {filepath}: {e}")
return None, f"openpyxl_open_error: {safe_str(e)}"
try:
if SHEET_NAME not in wb.sheetnames:
wb.close()
return None, "missing_sheet"
ws = wb[SHEET_NAME]
except Exception as e:
try:
wb.close()
except Exception:
pass
log(f"[openpyxl] Ошибка доступа к листу в {filepath}: {e}")
return None, f"openpyxl_sheet_error: {safe_str(e)}"
row = {
"ФИО": filepath.stem,
"Дата_файла": get_file_modified_datetime(filepath)
}
for col_name, cell_addr in CELLS_CONFIG.items():
try:
# ws[cell_addr] may raise if address invalid
value = ws[cell_addr].value
except Exception as e:
value = None
log(f" [openpyxl] Не удалось прочитать ячейку {cell_addr} в {filepath}: {e}")
row[col_name] = value
try:
wb.close()
except Exception:
pass
return row, "ok"
def process_with_pandas(filepath: Path):
# fallback: pandas.read_excel (may evaluate formulas differently, but we try)
try:
# engine openpyxl recommended
df = pd.read_excel(filepath, sheet_name=SHEET_NAME, engine="openpyxl", nrows=0)
except Exception as e:
log(f"[pandas] Не удалось открыть/прочитать {filepath} через pandas: {e}")
return None, f"pandas_error: {safe_str(e)}"
# если чтение прошло, попробуем читать нужные ячейки через pandas by using header=None and usecols?
# Но pandas не читает одиночные адреса легко; поэтому — пробуем прочитать целый лист и взять нужные ячейки по адресам.
try:
full = pd.read_excel(filepath, sheet_name=SHEET_NAME, engine="openpyxl")
except Exception as e:
log(f"[pandas] Не удалось считать полный лист {SHEET_NAME} из {filepath}: {e}")
return None, f"pandas_full_error: {safe_str(e)}"
row = {
"ФИО": filepath.stem,
"Дата_файла": get_file_modified_datetime(filepath)
}
# convert Excel-style address (like E46) to zero-based indices
def excel_addr_to_idx(addr: str):
# simple parser: letters then digits
letters = "".join([c for c in addr if c.isalpha()]).upper()
digits = "".join([c for c in addr if c.isdigit()])
if not letters or not digits:
raise ValueError(f"Invalid address: {addr}")
col = 0
for ch in letters:
col = col * 26 + (ord(ch) - ord('A') + 1)
col_idx = col - 1
row_idx = int(digits) - 1
return row_idx, col_idx
for col_name, cell_addr in CELLS_CONFIG.items():
try:
r, c = excel_addr_to_idx(cell_addr)
# pandas uses 0-based row index
val = full.iat[r, c]
except Exception as e:
val = None
log(f" [pandas] Не удалось получить {cell_addr} в {filepath}: {e}")
row[col_name] = val
return row, "ok"
def main():
ensure_log_header()
log("Запуск скрипта")
log(f"Python: {sys.version.replace(chr(10),' ')}")
cwd = Path.cwd()
log(f"Current working dir: {cwd}")
input_path = Path(INPUT_FOLDER)
log(f"INPUT_FOLDER resolved: {input_path.resolve()}")
if not input_path.exists():
log(f"[ОШИБКА] INPUT_FOLDER не найден: {input_path}")
return
# check write permission for output location
out_dir = Path(OUTPUT_FILE).resolve().parent
if not check_write_permission(out_dir):
log(f"[ОШИБКА] Скрипт не может записать в папку {out_dir}. Попробуй запустить с другими правами или изменить OUTPUT_FILE.")
# не выходим — попытаемся всё равно создать CSV в cwd если можно
else:
log(f"[OK] Права записи в папку {out_dir} имеются")
results = []
stats = {
"found": 0,
"processed_ok": 0,
"missing_sheet": 0,
"openp
full = pd.read_excel(filepath, sheet_name=SHEET_NAME, engine="openpyxl")
except Exception as e:
log(f"[pandas] Не удалось считать полный лист {SHEET_NAME} из {filepath}: {e}")
return None, f"pandas_full_error: {safe_str(e)}"
row = {
"ФИО": filepath.stem,
"Дата_файла": get_file_modified_datetime(filepath)
}
# convert Excel-style address (like E46) to zero-based indices
def excel_addr_to_idx(addr: str):
# simple parser: letters then digits
letters = "".join([c for c in addr if c.isalpha()]).upper()
digits = "".join([c for c in addr if c.isdigit()])
if not letters or not digits:
raise ValueError(f"Invalid address: {addr}")
col = 0
for ch in letters:
col = col * 26 + (ord(ch) - ord('A') + 1)
col_idx = col - 1
row_idx = int(digits) - 1
return row_idx, col_idx
for col_name, cell_addr in CELLS_CONFIG.items():
try:
r, c = excel_addr_to_idx(cell_addr)
# pandas uses 0-based row index
val = full.iat[r, c]
except Exception as e:
val = None
log(f" [pandas] Не удалось получить {cell_addr} в {filepath}: {e}")
row[col_name] = val
return row, "ok"
def main():
ensure_log_header()
log("Запуск скрипта")
log(f"Python: {sys.version.replace(chr(10),' ')}")
cwd = Path.cwd()
log(f"Current working dir: {cwd}")
input_path = Path(INPUT_FOLDER)
log(f"INPUT_FOLDER resolved: {input_path.resolve()}")
if not input_path.exists():
log(f"[ОШИБКА] INPUT_FOLDER не найден: {input_path}")
return
# check write permission for output location
out_dir = Path(OUTPUT_FILE).resolve().parent
if not check_write_permission(out_dir):
log(f"[ОШИБКА] Скрипт не может записать в папку {out_dir}. Попробуй запустить с другими правами или изменить OUTPUT_FILE.")
# не выходим — попытаемся всё равно создать CSV в cwd если можно
else:
log(f"[OK] Права записи в папку {out_dir} имеются")
results = []
stats = {
"found": 0,
"processed_ok": 0,
"missing_sheet": 0,
"openp
#!/usr/bin/env python3
# debug_excel_collector.py
import os
import sys
import datetime
import traceback
from pathlib import Path
import pandas as pd
from openpyxl import load_workbook
# ==========================
# КОНФИГУРАЦИЯ
# ==========================
# Установи тут корректный путь к папке с файлами
INPUT_FOLDER = r"PATH_TO_FOLDER" # <-- замените на ваш путь
OUTPUT_FILE = "result.xlsx"
OUTPUT_CSV = "result.csv"
SHEET_NAME = "Баллы"
CELLS_CONFIG = {
"Итого_Сумма": "E46",
"Пример": "C10"
}
LOG_FILE = "debug_log.txt"
# ==========================
def log(msg: str, *, end="\n"):
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
line = f"[{timestamp}] {msg}"
print(line, end=end)
try:
with open(LOG_FILE, "a", encoding="utf-8") as f:
f.write(line + ("\n" if end == "\n" else ""))
except Exception:
# best-effort logging; avoid infinite recursion if logging fails
print(f"[{timestamp}] [LOG ERROR] Не удалось записать в {LOG_FILE}")
def safe_str(x):
try:
return "" if x is None else str(x)
except Exception:
return "<non-stringable>"
def get_file_modified_datetime(path: Path) -> str:
try:
ts = path.stat().st_mtime
return datetime.datetime.fromtimestamp(ts).strftime("%Y-%m-%d %H:%M:%S")
except Exception:
return ""
def ensure_log_header():
try:
with open(LOG_FILE, "w", encoding="utf-8") as f:
f.write("Debug log for excel collector\n")
f.write(f"Start: {datetime.datetime.now().isoformat()}\n\n")
except Exception:
print("Не удалось создать лог-файл в текущей директории.")
def check_write_permission(path: Path) -> bool:
try:
test = path / ".write_test_tmp"
with open(test, "w", encoding="utf-8") as f:
f.write("test")
test.unlink()
return True
except Exception as e:
log(f"[ПРАВА] Нет прав на запись в папку {path}: {e}")
return False
def process_with_openpyxl(filepath: Path):
try:
wb = load_workbook(str(filepath), read_only=True, data_only=True)
except Exception as e:
log(f"[openpyxl] Ошибка открытия файла {filepath}: {e}")
return None, f"openpyxl_open_error: {safe_str(e)}"
try:
if SHEET_NAME not in wb.sheetnames:
wb.close()
return None, "missing_sheet"
ws = wb[SHEET_NAME]
except Exception as e:
try:
wb.close()
except Exception:
pass
log(f"[openpyxl] Ошибка доступа к листу в {filepath}: {e}")
return None, f"openpyxl_sheet_error: {safe_str(e)}"
row = {
"ФИО": filepath.stem,
"Дата_файла": get_file_modified_datetime(filepath)
}
for col_name, cell_addr in CELLS_CONFIG.items():
try:
# ws[cell_addr] may raise if address invalid
value = ws[cell_addr].value
except Exception as e:
value = None
log(f" [openpyxl] Не удалось прочитать ячейку {cell_addr} в {filepath}: {e}")
row[col_name] = value
try:
wb.close()
except Exception:
pass
return row, "ok"
def process_with_pandas(filepath: Path):
# fallback: pandas.read_excel (may evaluate formulas differently, but we try)
try:
# engine openpyxl recommended
df = pd.read_excel(filepath, sheet_name=SHEET_NAME, engine="openpyxl", nrows=0)
except Exception as e:
log(f"[pandas] Не удалось открыть/прочитать {filepath} через pandas: {e}")
return None, f"pandas_error: {safe_str(e)}"
# если чтение прошло, попробуем читать нужные ячейки через pandas by using header=None and usecols?
# Но pandas не читает одиночные адреса легко; поэтому — пробуем прочитать целый лист и взять нужные ячейки по адресам.
# debug_excel_collector.py
import os
import sys
import datetime
import traceback
from pathlib import Path
import pandas as pd
from openpyxl import load_workbook
# ==========================
# КОНФИГУРАЦИЯ
# ==========================
# Установи тут корректный путь к папке с файлами
INPUT_FOLDER = r"PATH_TO_FOLDER" # <-- замените на ваш путь
OUTPUT_FILE = "result.xlsx"
OUTPUT_CSV = "result.csv"
SHEET_NAME = "Баллы"
CELLS_CONFIG = {
"Итого_Сумма": "E46",
"Пример": "C10"
}
LOG_FILE = "debug_log.txt"
# ==========================
def log(msg: str, *, end="\n"):
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
line = f"[{timestamp}] {msg}"
print(line, end=end)
try:
with open(LOG_FILE, "a", encoding="utf-8") as f:
f.write(line + ("\n" if end == "\n" else ""))
except Exception:
# best-effort logging; avoid infinite recursion if logging fails
print(f"[{timestamp}] [LOG ERROR] Не удалось записать в {LOG_FILE}")
def safe_str(x):
try:
return "" if x is None else str(x)
except Exception:
return "<non-stringable>"
def get_file_modified_datetime(path: Path) -> str:
try:
ts = path.stat().st_mtime
return datetime.datetime.fromtimestamp(ts).strftime("%Y-%m-%d %H:%M:%S")
except Exception:
return ""
def ensure_log_header():
try:
with open(LOG_FILE, "w", encoding="utf-8") as f:
f.write("Debug log for excel collector\n")
f.write(f"Start: {datetime.datetime.now().isoformat()}\n\n")
except Exception:
print("Не удалось создать лог-файл в текущей директории.")
def check_write_permission(path: Path) -> bool:
try:
test = path / ".write_test_tmp"
with open(test, "w", encoding="utf-8") as f:
f.write("test")
test.unlink()
return True
except Exception as e:
log(f"[ПРАВА] Нет прав на запись в папку {path}: {e}")
return False
def process_with_openpyxl(filepath: Path):
try:
wb = load_workbook(str(filepath), read_only=True, data_only=True)
except Exception as e:
log(f"[openpyxl] Ошибка открытия файла {filepath}: {e}")
return None, f"openpyxl_open_error: {safe_str(e)}"
try:
if SHEET_NAME not in wb.sheetnames:
wb.close()
return None, "missing_sheet"
ws = wb[SHEET_NAME]
except Exception as e:
try:
wb.close()
except Exception:
pass
log(f"[openpyxl] Ошибка доступа к листу в {filepath}: {e}")
return None, f"openpyxl_sheet_error: {safe_str(e)}"
row = {
"ФИО": filepath.stem,
"Дата_файла": get_file_modified_datetime(filepath)
}
for col_name, cell_addr in CELLS_CONFIG.items():
try:
# ws[cell_addr] may raise if address invalid
value = ws[cell_addr].value
except Exception as e:
value = None
log(f" [openpyxl] Не удалось прочитать ячейку {cell_addr} в {filepath}: {e}")
row[col_name] = value
try:
wb.close()
except Exception:
pass
return row, "ok"
def process_with_pandas(filepath: Path):
# fallback: pandas.read_excel (may evaluate formulas differently, but we try)
try:
# engine openpyxl recommended
df = pd.read_excel(filepath, sheet_name=SHEET_NAME, engine="openpyxl", nrows=0)
except Exception as e:
log(f"[pandas] Не удалось открыть/прочитать {filepath} через pandas: {e}")
return None, f"pandas_error: {safe_str(e)}"
# если чтение прошло, попробуем читать нужные ячейки через pandas by using header=None and usecols?
# Но pandas не читает одиночные адреса легко; поэтому — пробуем прочитать целый лист и взять нужные ячейки по адресам.
try:
full = pd.read_excel(filepath, sheet_name=SHEET_NAME, engine="openpyxl")
except Exception as e:
log(f"[pandas] Не удалось считать полный лист {SHEET_NAME} из {filepath}: {e}")
return None, f"pandas_full_error: {safe_str(e)}"
row = {
"ФИО": filepath.stem,
"Дата_файла": get_file_modified_datetime(filepath)
}
# convert Excel-style address (like E46) to zero-based indices
def excel_addr_to_idx(addr: str):
# simple parser: letters then digits
letters = "".join([c for c in addr if c.isalpha()]).upper()
digits = "".join([c for c in addr if c.isdigit()])
if not letters or not digits:
raise ValueError(f"Invalid address: {addr}")
col = 0
for ch in letters:
col = col * 26 + (ord(ch) - ord('A') + 1)
col_idx = col - 1
row_idx = int(digits) - 1
return row_idx, col_idx
for col_name, cell_addr in CELLS_CONFIG.items():
try:
r, c = excel_addr_to_idx(cell_addr)
# pandas uses 0-based row index
val = full.iat[r, c]
except Exception as e:
val = None
log(f" [pandas] Не удалось получить {cell_addr} в {filepath}: {e}")
row[col_name] = val
return row, "ok"
def main():
ensure_log_header()
log("Запуск скрипта")
log(f"Python: {sys.version.replace(chr(10),' ')}")
cwd = Path.cwd()
log(f"Current working dir: {cwd}")
input_path = Path(INPUT_FOLDER)
log(f"INPUT_FOLDER resolved: {input_path.resolve()}")
if not input_path.exists():
log(f"[ОШИБКА] INPUT_FOLDER не найден: {input_path}")
return
# check write permission for output location
out_dir = Path(OUTPUT_FILE).resolve().parent
if not check_write_permission(out_dir):
log(f"[ОШИБКА] Скрипт не может записать в папку {out_dir}. Попробуй запустить с другими правами или изменить OUTPUT_FILE.")
# не выходим — попытаемся всё равно создать CSV в cwd если можно
else:
log(f"[OK] Права записи в папку {out_dir} имеются")
results = []
stats = {
"found": 0,
"processed_ok": 0,
"missing_sheet": 0,
"openpyxl_open_error": 0,
"openpyxl_sheet_error": 0,
"pandas_error": 0,
"other_errors": 0,
"skipped_temp": 0
}
found_files = []
for root, dirs, files in os.walk(input_path):
for f in files:
if f.startswith("~$"):
stats["skipped_temp"] += 1
continue
if not (f.lower().endswith(".xlsx") or f.lower().endswith(".xlsm")):
continue
full = Path(root) / f
stats["found"] += 1
found_files.append(full)
log(f"Всего найдено Excel-файлов: {stats['found']} (пропущено временных: {stats['skipped_temp']})")
# show up to first 10
for i, p in enumerate(found_files[:10], 1):
log(f" [{i}] {p}")
if stats["found"] == 0:
log("[INFO] Файлы не найдены. Проверь путь INPUT_FOLDER и расширения файлов.")
# Обработка
for idx, filepath in enumerate(found_files, 1):
log(f"\nОбрабатываю ({idx}/{len(found_files)}): {filepath}")
try:
row, status = process_with_openpyxl(filepath)
if status != "ok":
# increment corresponding stat
if status == "missing_sheet":
stats["missing_sheet"] += 1
log(f" → Пропущен: отсутствует лист {SHEET_NAME}")
elif status.startswith("openpyxl_open_error"):
stats["openpyxl_open_error"] += 1
log(f" → openpyxl не открыл файл: {status}")
else:
stats["other_errors"] += 1
full = pd.read_excel(filepath, sheet_name=SHEET_NAME, engine="openpyxl")
except Exception as e:
log(f"[pandas] Не удалось считать полный лист {SHEET_NAME} из {filepath}: {e}")
return None, f"pandas_full_error: {safe_str(e)}"
row = {
"ФИО": filepath.stem,
"Дата_файла": get_file_modified_datetime(filepath)
}
# convert Excel-style address (like E46) to zero-based indices
def excel_addr_to_idx(addr: str):
# simple parser: letters then digits
letters = "".join([c for c in addr if c.isalpha()]).upper()
digits = "".join([c for c in addr if c.isdigit()])
if not letters or not digits:
raise ValueError(f"Invalid address: {addr}")
col = 0
for ch in letters:
col = col * 26 + (ord(ch) - ord('A') + 1)
col_idx = col - 1
row_idx = int(digits) - 1
return row_idx, col_idx
for col_name, cell_addr in CELLS_CONFIG.items():
try:
r, c = excel_addr_to_idx(cell_addr)
# pandas uses 0-based row index
val = full.iat[r, c]
except Exception as e:
val = None
log(f" [pandas] Не удалось получить {cell_addr} в {filepath}: {e}")
row[col_name] = val
return row, "ok"
def main():
ensure_log_header()
log("Запуск скрипта")
log(f"Python: {sys.version.replace(chr(10),' ')}")
cwd = Path.cwd()
log(f"Current working dir: {cwd}")
input_path = Path(INPUT_FOLDER)
log(f"INPUT_FOLDER resolved: {input_path.resolve()}")
if not input_path.exists():
log(f"[ОШИБКА] INPUT_FOLDER не найден: {input_path}")
return
# check write permission for output location
out_dir = Path(OUTPUT_FILE).resolve().parent
if not check_write_permission(out_dir):
log(f"[ОШИБКА] Скрипт не может записать в папку {out_dir}. Попробуй запустить с другими правами или изменить OUTPUT_FILE.")
# не выходим — попытаемся всё равно создать CSV в cwd если можно
else:
log(f"[OK] Права записи в папку {out_dir} имеются")
results = []
stats = {
"found": 0,
"processed_ok": 0,
"missing_sheet": 0,
"openpyxl_open_error": 0,
"openpyxl_sheet_error": 0,
"pandas_error": 0,
"other_errors": 0,
"skipped_temp": 0
}
found_files = []
for root, dirs, files in os.walk(input_path):
for f in files:
if f.startswith("~$"):
stats["skipped_temp"] += 1
continue
if not (f.lower().endswith(".xlsx") or f.lower().endswith(".xlsm")):
continue
full = Path(root) / f
stats["found"] += 1
found_files.append(full)
log(f"Всего найдено Excel-файлов: {stats['found']} (пропущено временных: {stats['skipped_temp']})")
# show up to first 10
for i, p in enumerate(found_files[:10], 1):
log(f" [{i}] {p}")
if stats["found"] == 0:
log("[INFO] Файлы не найдены. Проверь путь INPUT_FOLDER и расширения файлов.")
# Обработка
for idx, filepath in enumerate(found_files, 1):
log(f"\nОбрабатываю ({idx}/{len(found_files)}): {filepath}")
try:
row, status = process_with_openpyxl(filepath)
if status != "ok":
# increment corresponding stat
if status == "missing_sheet":
stats["missing_sheet"] += 1
log(f" → Пропущен: отсутствует лист {SHEET_NAME}")
elif status.startswith("openpyxl_open_error"):
stats["openpyxl_open_error"] += 1
log(f" → openpyxl не открыл файл: {status}")
else:
stats["other_errors"] += 1
log(f" → openpyxl вернул статус: {status}")
else:
results.append(row)
stats["processed_ok"] += 1
log(" → Успешно (openpyxl)")
except Exception as e:
log(f" [EXCEPTION] при openpyxl: {e}")
log(traceback.format_exc())
stats["other_errors"] += 1
row = None
if row is None:
# fallback try pandas method to salvage values
try:
log(" Попытка fallback: pandas.read_excel")
row2, status2 = process_with_pandas(filepath)
if status2 == "ok" and row2 is not None:
results.append(row2)
stats["processed_ok"] += 1
log(" → Успешно (pandas fallback)")
else:
if status2 and "pandas_error" in status2:
stats["pandas_error"] += 1
log(f" → fallback не сработал: {status2}")
except Exception as e:
log(f" [FALLBACK EXCEPTION] {e}")
log(traceback.format_exc())
stats["other_errors"] += 1
# summary
log("\n=== Сводка ===")
for k, v in stats.items():
log(f"{k}: {v}")
log(f"Успешно обработано файлов: {stats['processed_ok']}")
# save results (CSV always)
try:
df = pd.DataFrame(results)
if df.empty:
# создаём пустой dataframe с заголовками, чтобы файл имел колонки
cols = ["ФИО", "Дата_файла"] + list(CELLS_CONFIG.keys())
df = pd.DataFrame(columns=cols)
# CSV first (guaranteed)
df.to_csv(OUTPUT_CSV, index=False, encoding="utf-8-sig")
log(f"[SAVE] Результат сохранён в CSV: {OUTPUT_CSV}")
except Exception as e:
log(f"[SAVE ERROR] Не удалось сохранить CSV {OUTPUT_CSV}: {e}")
log(traceback.format_exc())
# Try xlsx (best effort)
try:
df.to_excel(OUTPUT_FILE, index=False)
log(f"[SAVE] Результат сохранён в XLSX: {OUTPUT_FILE}")
except Exception as e:
log(f"[SAVE ERROR] Не удалось сохранить XLSX {OUTPUT_FILE}: {e}")
log(" Попробуй сохранить в другом каталоге или проверить права.")
log(traceback.format_exc())
log("Завершено.")
if name == "main":
main()
else:
results.append(row)
stats["processed_ok"] += 1
log(" → Успешно (openpyxl)")
except Exception as e:
log(f" [EXCEPTION] при openpyxl: {e}")
log(traceback.format_exc())
stats["other_errors"] += 1
row = None
if row is None:
# fallback try pandas method to salvage values
try:
log(" Попытка fallback: pandas.read_excel")
row2, status2 = process_with_pandas(filepath)
if status2 == "ok" and row2 is not None:
results.append(row2)
stats["processed_ok"] += 1
log(" → Успешно (pandas fallback)")
else:
if status2 and "pandas_error" in status2:
stats["pandas_error"] += 1
log(f" → fallback не сработал: {status2}")
except Exception as e:
log(f" [FALLBACK EXCEPTION] {e}")
log(traceback.format_exc())
stats["other_errors"] += 1
# summary
log("\n=== Сводка ===")
for k, v in stats.items():
log(f"{k}: {v}")
log(f"Успешно обработано файлов: {stats['processed_ok']}")
# save results (CSV always)
try:
df = pd.DataFrame(results)
if df.empty:
# создаём пустой dataframe с заголовками, чтобы файл имел колонки
cols = ["ФИО", "Дата_файла"] + list(CELLS_CONFIG.keys())
df = pd.DataFrame(columns=cols)
# CSV first (guaranteed)
df.to_csv(OUTPUT_CSV, index=False, encoding="utf-8-sig")
log(f"[SAVE] Результат сохранён в CSV: {OUTPUT_CSV}")
except Exception as e:
log(f"[SAVE ERROR] Не удалось сохранить CSV {OUTPUT_CSV}: {e}")
log(traceback.format_exc())
# Try xlsx (best effort)
try:
df.to_excel(OUTPUT_FILE, index=False)
log(f"[SAVE] Результат сохранён в XLSX: {OUTPUT_FILE}")
except Exception as e:
log(f"[SAVE ERROR] Не удалось сохранить XLSX {OUTPUT_FILE}: {e}")
log(" Попробуй сохранить в другом каталоге или проверить права.")
log(traceback.format_exc())
log("Завершено.")
if name == "main":
main()