Как лучше забрать значение формулы в Excel таблице через pandas?
Ссылка скопирована
По вводным: у меня есть функция, которая забирает данные из ексель таблицы и вставляет их в.docx документ, все данные четко забираются, кроме тех в которых есть ВПР формула, а именно значения section и dimensions
По вводным: section - =ВПР(RC[-1];R2C21:R16C22;2;1)
По вводным: dimensions - =ВПР(RC[-1];R18C21:R26C22;2;1)
Код:
def safe_get_number(value): if pd.isna(value) or value == "": return None try: num = float(str(value).replace(',', '.')) return int(num) if num.is_integer() else num except (ValueError, TypeError): return None async def process_matching_row(row, shu_number, index, message, bot): try: name_of_the_unit = row.iloc[2] if len(row) > 2 else "Не указано" serial_number = row.iloc[3] if len(row) > 3 else "Не указано" ip = int(row.iloc[18]) if len(row) > 17 else "Не указано" weight = safe_get_number(row.iloc[15]) if len(row) > 15 else None weight_display = f"{weight} кг" if weight is not None else "Не указано" A = row.iloc[4] if len(row) > 4 else "Не указано" section = row.iloc[6] if len(row) > 6 else "Не указано" # тут формула ВПР (выдает nan) voltage = int(row.iloc[8] if len(row) > 8 else "Не указано") rated_A = row.iloc[4] if len(row) > 4 else "Не указано" dimensions = row.iloc[14] if len(row) > 6 else "Не указано". #тут формула ВПР (выдает nan) sn = row.iloc[16] if len(row) > 16 else "Не указано" logger.info(row) try: doc = Document(passport_config.get_target_file()) replacements = { "Заводской номер:": f"Заводской номер: {str(serial_number)}", "Проект №": f"Проект № ШУ {shu_number}", "Шкаф №": f"Шкаф {str(name_of_the_unit)}", "Дата:": f"Дата: {datetime.now().strftime('%d.%m.%Y')}", "IP": f"IP{ip}", "A": f"{A}A", "`": f"{section}мм2", "~": f"{dimensions}мм", "± 10 %": f"{voltage}± 10 %", "}": f"{weight}кг", "{": f"{sn}" } def replace_text_with_style(paragraph, old_text, new_text): if old_text in paragraph.text: for run in paragraph.runs: if old_text in run.text: run.text = run.text.replace(old_text, new_text) for paragraph in doc.paragraphs: for old_text, new_text in replacements.items(): replace_text_with_style(paragraph, old_text, new_text) for table in doc.tables: for row in table.rows: for cell in row.cells: for paragraph in cell.paragraphs: for old_text, new_text in replacements.items(): replace_text_with_style(paragraph, old_text, new_text) output_filename = f"ШУ_{shu_number}_{serial_number}.docx" desktop_path = SHUConfig.get_directory_path() pattern = re.compile(r".*ШУ\s*" + re.escape(str(shu_number)) + r"\D*$", re.IGNORECASE) matching_folders = [] for folder_name in os.listdir(desktop_path): if pattern.search(folder_name): matching_folders.append(folder_name) save_path = "." if matching_folders: matching_folders.sort(reverse=True) folder_path = os.path.join(desktop_path, matching_folders[0]) pasporta_path = os.path.join(folder_path, "Паспорта") try: os.makedirs(pasporta_path, exist_ok=True) save_path = pasporta_path except Exception as e: save_path = folder_path output_path = os.path.join(save_path, output_filename) doc.save(output_path) logger.info(Fore.GREEN + f"✓ Документ сохранен: {output_path}" + Style.RESET_ALL) if matching_folders: pdf_file = None elektrika_path = os.path.join(folder_path, "электрика") if os.path.exists(elektrika_path): pdf_files = [f for f in os.listdir(elektrika_path) if f.lower().endswith('.pdf') and f.startswith('1')] if pdf_files: pdf_files.sort() pdf_file = os.path.join(elektrika_path, pdf_files[0]) if not pdf_file: pdf_files = [f for f in os.listdir(folder_path) if f.lower().endswith('.pdf') and f.startswith('1')] if pdf_files: pdf_files.sort() pdf_file = os.path.join(folder_path, pdf_files[0]) if pdf_file: if await process_pdf_attachment(pdf_file, pasporta_path, message, bot, shu_number): else: await bot.send_message(message.from_user.id, "Не найден PDF файл электрики!") except Exception as e: await bot.send_message(ADMIN_ID, f"× Ошибка в замене шаблона: {str(e)}") logger.error(Fore.RED + f"× Ошибка: {str(e)}" + Style.RESET_ALL) except Exception as e: await bot.send_message(ADMIN_ID, f"Ошибка при обработке строки {index + 1}: {e}") logger.error(Fore.RED + f"Ошибка при обработке строки {index + 1}: {e}" + Style.RESET_ALL) async def find_in_register(file_path, shu_number, message, bot): try: df = pd.read_excel(file_path) pattern = fr'(?:^|\b)ШУ\s*{re.escape(shu_number)}(?:\b|$)' mask = df.apply(lambda col: col.astype(str).str.contains(pattern, regex=True)).any(axis=1) matching_rows = df[mask] if not matching_rows.empty: logger.info(Fore.YELLOW + f"\nВсего найдено {len(matching_rows)} совпадений в реестре для ШУ{shu_number}:" + Style.RESET_ALL) for i, (_, row) in enumerate(matching_rows.iterrows()): await process_matching_row(row, shu_number, i, message, bot) else: await bot.send_message(message.from_user.id, f"\nВ реестре не найдено записей для ШУ{shu_number}") except Exception as e: await bot.send_message(message.from_user.id, f"Ошибка при поиске в реестре: {e}")
Нужно решить такую задачу?
Заказать помощь
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Лучший ответ
1
Другие ответы (0)
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопроскомментарий
Вам также может быть интересно
VPN
Как правильно настроить vless для Android TV?
1 ответ
Pyrogram
Как правильно зарегистрировать юзер бота в Telegram?
1 ответ
печатные-платы
Как заставить запускаться программу M3.exe от компании Hanxing AOI в инспекционной машине на Windows 7 Pro?
1 ответ
code-review
Нужен ли код-ревью React/TypeScript проекта?
1 ответ

Pandas сам по себе не вычисляет формулы Excel. Когда вы читаете файл через pandas/openpyxl, вы получаете либо текст формулы, либо последнее сохранённое Excel значение. Если файл был создан программно и ни разу не пересчитывался в Excel/LibreOffice, сохранённого значения у формулы может просто не быть.
Для получения именно результата ВПР есть три рабочих варианта.
Первый вариант - читать файл через openpyxl с data_only=True. Это вернёт кэшированное значение формулы, если оно есть:
from openpyxl import load_workbook wb = load_workbook('file.xlsx', data_only=True) ws = wb['Лист1'] section = ws['B2'].value dimensions = ws['C2'].value
Если возвращается None, значит Excel не сохранил рассчитанный результат. Тогда второй вариант - перед обработкой пересчитать файл в Excel или LibreOffice. Например, на сервере часто используют LibreOffice headless:
soffice --headless --convert-to xlsx --outdir ./recalc ./input.xlsx
Третий вариант - не полагаться на Excel-формулу, а повторить логику ВПР в Python. Это часто надёжнее, если вы генерируете документы автоматически:
main = pandas.read_excel('file.xlsx', sheet_name='main') dict_table = pandas.read_excel('file.xlsx', sheet_name='dict') main = main.merge( dict_table[['key', 'section', 'dimensions']], on='key', how='left' )
Если документ дальше уходит в .docx, я бы выбрал третий путь: забрать исходные таблицы, сделать merge в pandas и подставлять уже готовые значения. Тогда результат не зависит от того, открыт ли файл в Excel, пересчитались ли формулы и сохранил ли Excel кэш формулы. Формулы в исходном файле можно оставить для людей, но в автоматизации лучше считать данные на стороне Python.