import os
import pandas as pd
report_types = {
'by_retailer': 'Общие продажи по ритейлеру',
'by_shops': 'Продажи по магазину',
}
# Constants for indices in the filename parts for 'by_retailer' report type
REGION_NAME_INDEX_BY_RETAILER = 0
RETAILER_NAME_INDEX_BY_RETAILER = 1
OFFSET_INDEX_BY_RETAILER = 2
BARCODE_INDEX_BY_RETAILER = 3
SALES_INDEX_BY_RETAILER = 4
SHOPS_INDEX_BY_RETAILER = 5
ALL_SHOPS_INDEX_BY_RETAILER = 6
STOCK_FIRST_INDEX_BY_RETAILER = 7
STOCK_LAST_INDEX_BY_RETAILER = 8
PRICE_PURCH_INDEX_BY_RETAILER = 9
SHELF_PRICE_INDEX_BY_RETAILER = 10
CATEGORY_INDEX_BY_RETAILER = 11
# Constants for indices in the filename parts for 'by_shops' report type
REGION_NAME_INDEX_BY_SHOPS = 0
RETAILER_NAME_INDEX_BY_SHOPS = 1
SHOP_NAME_INDEX_BY_SHOPS = 2
SALES_INDEX_BY_SHOPS = 3
RESIDUAL_INDEX_BY_SHOPS = 4
class ExcelValidator:
def __init__(self, file_path, report_type):
"""
Инициализирует ExcelValidator с путем к Excel файлу и типом отчета.
Args:
- file_path (str): Путь к Excel файлу для валидации.
- report_type (str): Тип отчета ('by_retailer' или 'by_shops').
"""
self.file_path = file_path
self.data_dict = {} # Словарь для хранения данных, извлеченных из имени файла
self.report_type = report_type
if self.report_type not in report_types:
raise ValueError(f"Неверный тип отчета: {self.report_type}. Допустимые типы: {list(report_types.keys())}")
def parse_filename(self, file_name):
"""
Парсит имя файла и заполняет data_dict извлеченными данными, если формат корректный.
Args:
- file_name (str): Имя файла для парсинга.
Raises:
- ValueError: Если формат имени файла неверен.
"""
name_without_extension = os.path.splitext(file_name)[0]
name_parts = name_without_extension.split('_')
# Выбираем соответствующие индексы на основе типа отчета
if self.report_type == 'by_retailer':
expected_parts = 12 # Настройте при необходимости для 'by_retailer'
# Проверяем, что в имени файла ожидаемое количество частей
if len(name_parts) != expected_parts:
raise ValueError(f"Неверный формат имени файла для '{self.report_type}'. Ожидается {expected_parts} частей, получено {len(name_parts)}.")
self.data_dict = {
'region': name_parts[REGION_NAME_INDEX_BY_RETAILER],
'retailer': name_parts[RETAILER_NAME_INDEX_BY_RETAILER],
'offset': name_parts[OFFSET_INDEX_BY_RETAILER],
'barcode': name_parts[BARCODE_INDEX_BY_RETAILER],
'sales': name_parts[SALES_INDEX_BY_RETAILER],
'shops': name_parts[SHOPS_INDEX_BY_RETAILER],
'all_shops': name_parts[ALL_SHOPS_INDEX_BY_RETAILER],
'stock_first': name_parts[STOCK_FIRST_INDEX_BY_RETAILER],
'stock_last': name_parts[STOCK_LAST_INDEX_BY_RETAILER],
'price_purch': name_parts[PRICE_PURCH_INDEX_BY_RETAILER],
'shelf_price': name_parts[SHELF_PRICE_INDEX_BY_RETAILER],
'category': name_parts[CATEGORY_INDEX_BY_RETAILER],
}
elif self.report_type == 'by_shops':
expected_parts = 5 # Настройте при необходимости для 'by_shops'
# Проверяем, что в имени файла ожидаемое количество частей
if len(name_parts) != expected_parts:
raise ValueError(f"Неверный формат имени файла для '{self.report_type}'. Ожидается {expected_parts} частей, получено {len(name_parts)}.")
self.data_dict = {
'region': name_parts[REGION_NAME_INDEX_BY_SHOPS],
'retailer': name_parts[RETAILER_NAME_INDEX_BY_SHOPS],
'shop_name': name_parts[SHOP_NAME_INDEX_BY_SHOPS],
'sales': name_parts[SALES_INDEX_BY_SHOPS],
'residual': name_parts[RESIDUAL_INDEX_BY_SHOPS],
}
else:
raise ValueError(f"Неизвестный тип отчета: {self.report_type}")
def validate_excel_file(self):
"""
Валидирует Excel файл по указанному пути.
Raises:
- FileNotFoundError: Если файл не найден.
- ValueError: Если файл не является Excel файлом.
- Exception: Если чтение Excel файла не удалось.
"""
if not os.path.isfile(self.file_path):
raise FileNotFoundError(f"Файл не найден по указанному пути: {self.file_path}")
file_name = os.path.basename(self.file_path)
# Проверяем, что файл является Excel файлом по расширению
if not file_name.endswith(('.xls', '.xlsx', '.xlsm')):
raise ValueError("Файл не является Excel файлом. Пожалуйста, предоставьте файл с расширением .xls, .xlsx или .xlsm.")
# Парсим имя файла
self.parse_filename(file_name)
# Читаем Excel файл с помощью pandas
try:
df = pd.read_excel(self.file_path)
# Здесь можно добавить дополнительную валидацию DataFrame
except Exception as e:
raise Exception(f"Ошибка при чтении Excel файла: {e}")
# Пример использования
if __name__ == '__main__':
# Для отчета 'by_retailer'
file_path_retailer = 'TEST_Tesco_5_1_2_3_500_0_0_0_0_4.xls' # Замените на ваш фактический путь к файлу
validator_retailer = ExcelValidator(file_path_retailer, report_type='by_retailer')
try:
validator_retailer.validate_excel_file()
print("Файл успешно валидирован.")
print("Data dictionary:", validator_retailer.data_dict)
except Exception as e:
print(f"Ошибка при валидации файла: {e}")