130 lines
6.0 KiB
Python
130 lines
6.0 KiB
Python
import pandas as pd
|
||
import os
|
||
import glob
|
||
|
||
|
||
class vault():
|
||
def __init__(self):
|
||
"""Простой класс для работы с Excel файлами"""
|
||
pass
|
||
|
||
def file_filter(self, dir_name):
|
||
"""Алгоритм 1: Перебор файлов в директории"""
|
||
print(f"Ищем в директории: {dir_name}")
|
||
print(f"Полный путь: {os.path.abspath(dir_name)}")
|
||
|
||
if not os.path.exists(dir_name):
|
||
print(f"Директория {dir_name} не существует")
|
||
return []
|
||
|
||
# Показываем все файлы в директории
|
||
all_files = os.listdir(dir_name)
|
||
print(f"Все файлы в директории: {len(all_files)} файлов")
|
||
|
||
# Поиск всех xls и xlsx файлов
|
||
pattern_xlsx = os.path.join(dir_name, "*.xlsx")
|
||
pattern_xls = os.path.join(dir_name, "*.xls")
|
||
print(f"Паттерн поиска xlsx: {pattern_xlsx}")
|
||
print(f"Паттерн поиска xls: {pattern_xls}")
|
||
|
||
xlsx_files = glob.glob(pattern_xlsx)
|
||
xls_files = glob.glob(pattern_xls)
|
||
|
||
# Объединяем все Excel файлы
|
||
excel_files = xlsx_files + xls_files
|
||
|
||
# Исключаем временные файлы Excel (начинающиеся с ~$)
|
||
excel_files = [f for f in excel_files if not os.path.basename(f).startswith('~$')]
|
||
|
||
print(f"Найдено {len(excel_files)} Excel файлов:")
|
||
for file in excel_files:
|
||
print(f" - {os.path.basename(file)}")
|
||
|
||
return excel_files
|
||
|
||
def open_xlsx(self, file_name, header_rows=1, row_filter=None):
|
||
"""Алгоритм 2: Перебор строк документа с настраиваемой шапкой и фильтром"""
|
||
try:
|
||
# Пробуем разные движки для чтения файлов
|
||
if file_name.endswith('.xls'):
|
||
# Для старых файлов .xls используем xlrd
|
||
df = pd.read_excel(file_name, header=list(range(header_rows)), engine='xlrd')
|
||
else:
|
||
# Для .xlsx используем openpyxl
|
||
df = pd.read_excel(file_name, header=list(range(header_rows)), engine='openpyxl')
|
||
|
||
print(f"Файл {os.path.basename(file_name)}: загружено {len(df)} строк")
|
||
|
||
# Применяем пользовательский фильтр если он задан
|
||
if row_filter and callable(row_filter):
|
||
original_count = len(df)
|
||
df = df[df.apply(row_filter, axis=1)]
|
||
filtered_count = len(df)
|
||
print(f"После фильтрации: {filtered_count} строк (исключено {original_count - filtered_count})")
|
||
|
||
return df
|
||
|
||
except Exception as e:
|
||
print(f"Ошибка при открытии файла {file_name}: {e}")
|
||
# Пробуем альтернативный способ
|
||
try:
|
||
print(f"Пробуем альтернативный движок для {os.path.basename(file_name)}")
|
||
df = pd.read_excel(file_name, header=list(range(header_rows)), engine='calamine')
|
||
print(f"Успешно загружено {len(df)} строк альтернативным способом")
|
||
|
||
if row_filter and callable(row_filter):
|
||
original_count = len(df)
|
||
df = df[df.apply(row_filter, axis=1)]
|
||
filtered_count = len(df)
|
||
print(f"После фильтрации: {filtered_count} строк")
|
||
|
||
return df
|
||
except Exception as e2:
|
||
print(f"Альтернативный способ тоже не сработал: {e2}")
|
||
return pd.DataFrame()
|
||
|
||
def merge_files(self, dir_name, output_file="merged.xlsx", header_rows=1, row_filter=None):
|
||
"""Объединяет файлы с настройками шапки и фильтра"""
|
||
# Алгоритм 1: находим файлы
|
||
files = self.file_filter(dir_name)
|
||
|
||
if not files:
|
||
print("Файлы не найдены")
|
||
return
|
||
|
||
all_data = []
|
||
|
||
# Алгоритм 2: обрабатываем каждый файл
|
||
for file_path in files:
|
||
df = self.open_xlsx(file_path, header_rows, row_filter)
|
||
if not df.empty:
|
||
# Добавляем информацию об источнике
|
||
df['_источник'] = os.path.basename(file_path)
|
||
all_data.append(df)
|
||
|
||
if all_data:
|
||
# Объединяем все данные
|
||
result = pd.concat(all_data, ignore_index=True)
|
||
|
||
# Сохраняем результат
|
||
result.to_excel(output_file, index=False)
|
||
print(f"\nОбъединено {len(result)} строк в файл {output_file}")
|
||
else:
|
||
print("Нет данных для объединения")
|
||
|
||
|
||
# Примеры использования
|
||
if __name__ == "__main__":
|
||
vault_instance = vault()
|
||
|
||
print("\n=== Пример 3: С фильтром строк ===")
|
||
def my_filter(row):
|
||
# Исключаем строки где первый столбец пустой
|
||
return not pd.isna(row.iloc[0]) and row.iloc[0] != ""
|
||
|
||
# Ищем файлы в папке ПРИЕММ и сохраняем результат как merged.xlsx
|
||
# Попробуйте с разными вариантами имени папки:
|
||
vault_instance.merge_files(".\ПРИЕММ", "merged.xlsx", row_filter=my_filter)
|
||
# или
|
||
# vault_instance.merge_files(r"ПРИЕММ", "merged.xlsx", row_filter=my_filter)
|