Добавить начальную структуру проекта с основными файлами и зависимостями
This commit is contained in:
13
.gitignore
vendored
Normal file
13
.gitignore
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Python-generated files
|
||||||
|
__pycache__/
|
||||||
|
*.py[oc]
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
wheels/
|
||||||
|
*.egg-info
|
||||||
|
|
||||||
|
# Virtual environments
|
||||||
|
.venv
|
||||||
|
|
||||||
|
# Files
|
||||||
|
files/
|
||||||
1
.python-version
Normal file
1
.python-version
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3.13
|
||||||
311
main.ipynb
Normal file
311
main.ipynb
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 70,
|
||||||
|
"id": "c7f0feca",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"import pandas as pd\n",
|
||||||
|
"import openpyxl\n",
|
||||||
|
"import os\n",
|
||||||
|
"from tqdm import tqdm\n",
|
||||||
|
"from datetime import datetime"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 71,
|
||||||
|
"id": "c3d2a034",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"DB_FILE = 'files/source.xlsx'\n",
|
||||||
|
"TEMPLATE_FILE = 'files/template.xlsx'\n",
|
||||||
|
"OUTPUT_FOLDER = 'files/output/'\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"MAPPING = {\n",
|
||||||
|
" 'Дата МО' : 'Q1',\n",
|
||||||
|
" 'Время МО' : 'Q2',\n",
|
||||||
|
" 'Номер направления': 'A13',\n",
|
||||||
|
" 'Фамилия, имя, отчество': 'D21',\n",
|
||||||
|
" 'Дата рождения': 'D22',\n",
|
||||||
|
" 'Структурное подразделение': 'F26',\n",
|
||||||
|
" 'Должность работника ': 'F27',\n",
|
||||||
|
" '''Наименование вредных производственных факторов или фидов работ (приложение к приказу Минздрава РФ от 28.01.2021 №29Н)''': 'F30'\n",
|
||||||
|
"}\n",
|
||||||
|
"\n",
|
||||||
|
"if not os.path.exists(OUTPUT_FOLDER):\n",
|
||||||
|
" os.makedirs(OUTPUT_FOLDER)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 72,
|
||||||
|
"id": "753709e8",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"Всего сотрудников в списке: 1482\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"Index(['Дата МО', 'Время МО', 'Номер направления', 'Фамилия, имя, отчество',\n",
|
||||||
|
" 'Должность работника ', 'Дата рождения', 'Структурное подразделение',\n",
|
||||||
|
" 'Наименование вредных производственных факторов или фидов работ (приложение к приказу Минздрава РФ от 28.01.2021 №29Н)',\n",
|
||||||
|
" 'Примечания'],\n",
|
||||||
|
" dtype='object')"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 72,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"df = pd.read_excel(DB_FILE)\n",
|
||||||
|
"print(f\"Всего сотрудников в списке: {len(df)}\")\n",
|
||||||
|
"# print(df.columns.tolist())\n",
|
||||||
|
"\n",
|
||||||
|
"df.columns"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 73,
|
||||||
|
"id": "dca336b7",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/html": [
|
||||||
|
"<div>\n",
|
||||||
|
"<style scoped>\n",
|
||||||
|
" .dataframe tbody tr th:only-of-type {\n",
|
||||||
|
" vertical-align: middle;\n",
|
||||||
|
" }\n",
|
||||||
|
"\n",
|
||||||
|
" .dataframe tbody tr th {\n",
|
||||||
|
" vertical-align: top;\n",
|
||||||
|
" }\n",
|
||||||
|
"\n",
|
||||||
|
" .dataframe thead th {\n",
|
||||||
|
" text-align: right;\n",
|
||||||
|
" }\n",
|
||||||
|
"</style>\n",
|
||||||
|
"<table border=\"1\" class=\"dataframe\">\n",
|
||||||
|
" <thead>\n",
|
||||||
|
" <tr style=\"text-align: right;\">\n",
|
||||||
|
" <th></th>\n",
|
||||||
|
" <th>Дата МО</th>\n",
|
||||||
|
" <th>Время МО</th>\n",
|
||||||
|
" <th>Номер направления</th>\n",
|
||||||
|
" <th>Фамилия, имя, отчество</th>\n",
|
||||||
|
" <th>Должность работника</th>\n",
|
||||||
|
" <th>Дата рождения</th>\n",
|
||||||
|
" <th>Структурное подразделение</th>\n",
|
||||||
|
" <th>Наименование вредных производственных факторов или фидов работ (приложение к приказу Минздрава РФ от 28.01.2021 №29Н)</th>\n",
|
||||||
|
" <th>Примечания</th>\n",
|
||||||
|
" </tr>\n",
|
||||||
|
" </thead>\n",
|
||||||
|
" <tbody>\n",
|
||||||
|
" <tr>\n",
|
||||||
|
" <th>0</th>\n",
|
||||||
|
" <td>2026-02-02</td>\n",
|
||||||
|
" <td>09:30</td>\n",
|
||||||
|
" <td>1</td>\n",
|
||||||
|
" <td>Орлова Ксения Николаевна</td>\n",
|
||||||
|
" <td>Доцент</td>\n",
|
||||||
|
" <td>17.07.1985</td>\n",
|
||||||
|
" <td>кафедра радиационной физики и безопасности ато...</td>\n",
|
||||||
|
" <td>4.1</td>\n",
|
||||||
|
" <td>NaN</td>\n",
|
||||||
|
" </tr>\n",
|
||||||
|
" <tr>\n",
|
||||||
|
" <th>1</th>\n",
|
||||||
|
" <td>2026-02-02</td>\n",
|
||||||
|
" <td>09:35</td>\n",
|
||||||
|
" <td>2</td>\n",
|
||||||
|
" <td>Камнев Владимир Александрович</td>\n",
|
||||||
|
" <td>Специалист по учебно-методической работе 1 кат...</td>\n",
|
||||||
|
" <td>24.01.1955</td>\n",
|
||||||
|
" <td>кафедра радиационной физики и безопасности ато...</td>\n",
|
||||||
|
" <td>4.1</td>\n",
|
||||||
|
" <td>NaN</td>\n",
|
||||||
|
" </tr>\n",
|
||||||
|
" <tr>\n",
|
||||||
|
" <th>2</th>\n",
|
||||||
|
" <td>2026-02-02</td>\n",
|
||||||
|
" <td>09:40</td>\n",
|
||||||
|
" <td>3</td>\n",
|
||||||
|
" <td>Стогов Юрий Владимирович</td>\n",
|
||||||
|
" <td>Доцент</td>\n",
|
||||||
|
" <td>05.01.1959</td>\n",
|
||||||
|
" <td>кафедра теоретической и экспериментальной физи...</td>\n",
|
||||||
|
" <td>4.1</td>\n",
|
||||||
|
" <td>NaN</td>\n",
|
||||||
|
" </tr>\n",
|
||||||
|
" <tr>\n",
|
||||||
|
" <th>3</th>\n",
|
||||||
|
" <td>2026-02-02</td>\n",
|
||||||
|
" <td>09:45</td>\n",
|
||||||
|
" <td>4</td>\n",
|
||||||
|
" <td>Алферов Владимир Петрович</td>\n",
|
||||||
|
" <td>Заместитель главного инженера исследовательско...</td>\n",
|
||||||
|
" <td>08.11.1948</td>\n",
|
||||||
|
" <td>исследовательский реактор типовой атомного центра</td>\n",
|
||||||
|
" <td>4.1</td>\n",
|
||||||
|
" <td>NaN</td>\n",
|
||||||
|
" </tr>\n",
|
||||||
|
" <tr>\n",
|
||||||
|
" <th>4</th>\n",
|
||||||
|
" <td>2026-02-02</td>\n",
|
||||||
|
" <td>09:50</td>\n",
|
||||||
|
" <td>5</td>\n",
|
||||||
|
" <td>Савостиков Сергей Алексеевич</td>\n",
|
||||||
|
" <td>Слесарь по ремонту и обслуживанию систем венти...</td>\n",
|
||||||
|
" <td>20.05.1988</td>\n",
|
||||||
|
" <td>теплоэнергетический отдел службы главного инже...</td>\n",
|
||||||
|
" <td>5.1, 6.2</td>\n",
|
||||||
|
" <td>NaN</td>\n",
|
||||||
|
" </tr>\n",
|
||||||
|
" </tbody>\n",
|
||||||
|
"</table>\n",
|
||||||
|
"</div>"
|
||||||
|
],
|
||||||
|
"text/plain": [
|
||||||
|
" Дата МО Время МО Номер направления Фамилия, имя, отчество \\\n",
|
||||||
|
"0 2026-02-02 09:30 1 Орлова Ксения Николаевна \n",
|
||||||
|
"1 2026-02-02 09:35 2 Камнев Владимир Александрович \n",
|
||||||
|
"2 2026-02-02 09:40 3 Стогов Юрий Владимирович \n",
|
||||||
|
"3 2026-02-02 09:45 4 Алферов Владимир Петрович \n",
|
||||||
|
"4 2026-02-02 09:50 5 Савостиков Сергей Алексеевич \n",
|
||||||
|
"\n",
|
||||||
|
" Должность работника Дата рождения \\\n",
|
||||||
|
"0 Доцент 17.07.1985 \n",
|
||||||
|
"1 Специалист по учебно-методической работе 1 кат... 24.01.1955 \n",
|
||||||
|
"2 Доцент 05.01.1959 \n",
|
||||||
|
"3 Заместитель главного инженера исследовательско... 08.11.1948 \n",
|
||||||
|
"4 Слесарь по ремонту и обслуживанию систем венти... 20.05.1988 \n",
|
||||||
|
"\n",
|
||||||
|
" Структурное подразделение \\\n",
|
||||||
|
"0 кафедра радиационной физики и безопасности ато... \n",
|
||||||
|
"1 кафедра радиационной физики и безопасности ато... \n",
|
||||||
|
"2 кафедра теоретической и экспериментальной физи... \n",
|
||||||
|
"3 исследовательский реактор типовой атомного центра \n",
|
||||||
|
"4 теплоэнергетический отдел службы главного инже... \n",
|
||||||
|
"\n",
|
||||||
|
" Наименование вредных производственных факторов или фидов работ (приложение к приказу Минздрава РФ от 28.01.2021 №29Н) \\\n",
|
||||||
|
"0 4.1 \n",
|
||||||
|
"1 4.1 \n",
|
||||||
|
"2 4.1 \n",
|
||||||
|
"3 4.1 \n",
|
||||||
|
"4 5.1, 6.2 \n",
|
||||||
|
"\n",
|
||||||
|
" Примечания \n",
|
||||||
|
"0 NaN \n",
|
||||||
|
"1 NaN \n",
|
||||||
|
"2 NaN \n",
|
||||||
|
"3 NaN \n",
|
||||||
|
"4 NaN "
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 73,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"df.head()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 74,
|
||||||
|
"id": "94ab472b",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"100%|██████████| 1482/1482 [00:54<00:00, 27.41it/s]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"\n",
|
||||||
|
"Файлы сохранены в 'files/output/'\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"for index, row in tqdm(df.iterrows(), total=len(df)):\n",
|
||||||
|
" wb = openpyxl.load_workbook(TEMPLATE_FILE)\n",
|
||||||
|
" ws = wb.active\n",
|
||||||
|
"\n",
|
||||||
|
" # Заполняем поля по словарю MAPPING\n",
|
||||||
|
" for excel_col, cell_address in MAPPING.items():\n",
|
||||||
|
" value = row.get(excel_col, \"\")\n",
|
||||||
|
"\n",
|
||||||
|
" if pd.isna(value):\n",
|
||||||
|
" value = \"\"\n",
|
||||||
|
"\n",
|
||||||
|
" if cell_address == 'A13':\n",
|
||||||
|
" ws[cell_address] = f\"НАПРАВЛЕНИЕ № {value}\"\n",
|
||||||
|
"\n",
|
||||||
|
" elif isinstance(value, (datetime, pd.Timestamp)):\n",
|
||||||
|
" ws[cell_address] = value.strftime('%d.%m.%Y')\n",
|
||||||
|
"\n",
|
||||||
|
" else:\n",
|
||||||
|
" ws[cell_address] = str(value)\n",
|
||||||
|
"\n",
|
||||||
|
" num = str(row.get('Номер направления', index + 1))\n",
|
||||||
|
" fio = str(row.get('Фамилия, имя, отчество')).strip().replace(' ', '_')\n",
|
||||||
|
" file_name = f\"Направление_№{num}_{fio}.xlsx\"\n",
|
||||||
|
"\n",
|
||||||
|
" save_path = os.path.join(OUTPUT_FOLDER, file_name)\n",
|
||||||
|
" wb.save(save_path)\n",
|
||||||
|
"\n",
|
||||||
|
"print(f\"\\nФайлы сохранены в '{OUTPUT_FOLDER}'\")"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "med-check-generator",
|
||||||
|
"language": "python",
|
||||||
|
"name": "python3"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.13.11"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
||||||
54
main.py
Normal file
54
main.py
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import pandas as pd
|
||||||
|
import openpyxl
|
||||||
|
import os
|
||||||
|
from tqdm import tqdm
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
DB_FILE = 'files/source.xlsx'
|
||||||
|
TEMPLATE_FILE = 'files/template.xlsx'
|
||||||
|
OUTPUT_FOLDER = 'files/output/'
|
||||||
|
|
||||||
|
MAPPING = {
|
||||||
|
'Дата МО': 'Q1',
|
||||||
|
'Время МО': 'Q2',
|
||||||
|
'Номер направления': 'A13',
|
||||||
|
'Фамилия, имя, отчество': 'D21',
|
||||||
|
'Дата рождения': 'D22',
|
||||||
|
'Структурное подразделение': 'F26',
|
||||||
|
'Должность работника ': 'F27',
|
||||||
|
'''Наименование вредных производственных факторов или фидов работ (приложение к приказу Минздрава РФ от 28.01.2021 №29Н)''': 'F30'
|
||||||
|
}
|
||||||
|
|
||||||
|
if not os.path.exists(OUTPUT_FOLDER):
|
||||||
|
os.makedirs(OUTPUT_FOLDER)
|
||||||
|
|
||||||
|
df = pd.read_excel(DB_FILE)
|
||||||
|
print(f"Всего сотрудников в списке: {len(df)}")
|
||||||
|
|
||||||
|
for index, row in tqdm(df.iterrows(), total=len(df), desc="Обработка"):
|
||||||
|
wb = openpyxl.load_workbook(TEMPLATE_FILE)
|
||||||
|
ws = wb.active
|
||||||
|
|
||||||
|
for excel_col, cell_address in MAPPING.items():
|
||||||
|
value = row.get(excel_col, "")
|
||||||
|
|
||||||
|
if pd.isna(value):
|
||||||
|
value = ""
|
||||||
|
|
||||||
|
if cell_address == 'A13':
|
||||||
|
ws[cell_address] = f"НАПРАВЛЕНИЕ № {value}" # type: ignore
|
||||||
|
|
||||||
|
elif isinstance(value, (datetime, pd.Timestamp)):
|
||||||
|
ws[cell_address] = value.strftime('%d.%m.%Y') # type: ignore
|
||||||
|
|
||||||
|
else:
|
||||||
|
ws[cell_address] = str(value) # type: ignore
|
||||||
|
|
||||||
|
num = str(row.get('Номер направления', index + 1)) # type: ignore
|
||||||
|
fio = str(row.get('Фамилия, имя, отчество')).strip().replace(' ', '_')
|
||||||
|
file_name = f"Направление_№{num}_{fio}.xlsx"
|
||||||
|
|
||||||
|
save_path = os.path.join(OUTPUT_FOLDER, file_name)
|
||||||
|
wb.save(save_path)
|
||||||
|
|
||||||
|
print(f"\nГотово! Файлы сохранены в '{OUTPUT_FOLDER}'")
|
||||||
7
pyproject.toml
Normal file
7
pyproject.toml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[project]
|
||||||
|
name = "med-check-generator"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Add your description here"
|
||||||
|
readme = "README.md"
|
||||||
|
requires-python = ">=3.13"
|
||||||
|
dependencies = []
|
||||||
4
requirements.txt
Normal file
4
requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
pandas
|
||||||
|
docxtpl
|
||||||
|
openpyxl
|
||||||
|
tqdm
|
||||||
Reference in New Issue
Block a user