Добавить начальную структуру проекта с основными файлами и зависимостями

This commit is contained in:
Dmitry
2025-12-28 17:40:25 +03:00
commit 904bc48138
8 changed files with 398 additions and 0 deletions

13
.gitignore vendored Normal file
View 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
View File

@@ -0,0 +1 @@
3.13

0
README.md Normal file
View File

311
main.ipynb Normal file
View 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
View 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
View 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
View File

@@ -0,0 +1,4 @@
pandas
docxtpl
openpyxl
tqdm

8
uv.lock generated Normal file
View File

@@ -0,0 +1,8 @@
version = 1
revision = 3
requires-python = ">=3.13"
[[package]]
name = "med-check-generator"
version = "0.1.0"
source = { virtual = "." }