/
kuzant24
/
libre-macros
Обзор
Документация
Войти
/
kuzant24
/
libre-macros
Код
Запросы
1
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
normilize_function
macro-lib/pythonpath/libre_macros_param_wizard_cfg.py
1 664 строки
94 KB
direct-dev.ru
to_work
28 июл 2026, 05:31
28 июл 2026, 05:31
b797194
Код
Авторство
О чём код?
# -*- coding: utf-8 -*- """Константы и состояние param_wizard (AlterOffice 2026).""" from __future__ import print_function, unicode_literals MACRO_VERSION = "3.10.295" import re try: unicode except NameError: unicode = str try: unichr except NameError: unichr = chr PARAM_WIZARD_DEBUG = False PARAM_WIZARD_TIMING = True _PW_TIME_DEPTH = 0 _UI_VSCALE = 0.8 # Мягкая серая палитра для диалога «применить_формулу» (не сливается со светлой темой). # Цвета UNO: 0x00RRGGBB. # Системный TitleBar (GTK/WM) через UNO обычно не красится — тёмный «титл» рисуем # полосой SoftGrayTitleBar внутри окна. _SOFT_GRAY_FORM_BG = 0xE6E6E6 _SOFT_GRAY_TITLE_BG = 0x4A4A4A _SOFT_GRAY_TITLE_FG = 0xF5F5F5 _SOFT_GRAY_LABEL_FG = 0x2A2A2A _SOFT_GRAY_FIELD_BG = 0xF4F4F4 _SOFT_GRAY_BTN_BG = 0xD4D4D4 _SOFT_GRAY_TITLE_H = 28 def _ui_v(n): return max(1, int(round(float(n) * _UI_VSCALE))) _DLG_W = 560 _M = 10 _FIELD_W = _DLG_W - _M * 2 _BROWSE_W = 92 _CTRL_H = _ui_v(22) _LBL_H = _ui_v(18) _GAP_S = _ui_v(6) _GAP_L = _ui_v(10) _BTN_H_MAIN = max(1, int(round(_ui_v(28) * 0.7))) _TAB_Y = _ui_v(10) _SHEET_COMBO_W = 168 _NEW_MODE_Y = _TAB_Y + _CTRL_H + _GAP_S _MODE_ROW_H = _CTRL_H _MODE_GAP = _GAP_S _MODE_BTN_LABEL_EDIT = u"Переключить на Новый параметр" _MODE_BTN_LABEL_NEW = u"Переключить в Редактирование" _MODE_BTN_W = 260 _MODE_BTN_X = _M + _FIELD_W - _MODE_BTN_W _MODE_LBL_W = _MODE_BTN_X - _M - _MODE_GAP _PAGE_TOP = _NEW_MODE_Y + _MODE_ROW_H + _GAP_L _PARAM_DISABLED_CHK_Y = _PAGE_TOP + _ui_v(44) + _GAP_S _PARAM_DISABLED_CHK_H = _LBL_H _VALUE_LBL_Y = _PAGE_TOP + _ui_v(68) _VALUE_LBL_TALL_H = _ui_v(32) _VALUE_CTRL_Y = _PAGE_TOP + _ui_v(86) _VALUE_CTRL_Y_TALL = _VALUE_LBL_Y + _VALUE_LBL_TALL_H + _GAP_S _VALUE_CTRL_H = _CTRL_H _VALUE_BTNS_Y = _VALUE_CTRL_Y + _VALUE_CTRL_H + _GAP_S _FILES_BTN_H = _CTRL_H _FILES_BTN_W = 128 _FILES_BTN_GAP = _ui_v(8) _EXTRA_LBL_Y = _VALUE_BTNS_Y + _FILES_BTN_H + _GAP_L _EXTRA_EDIT_Y = _EXTRA_LBL_Y + _LBL_H _EXTRA_EDIT_H = _CTRL_H _HIDDEN_CTRL_Y = -5000 _TRANSFER_PAIR_LBL_Y = _VALUE_BTNS_Y _TRANSFER_PAIR_CTRL_Y = _TRANSFER_PAIR_LBL_Y + _LBL_H _TRANSFER_WIZARD_DEFAULT = u"По_API" _DESC_Y = _EXTRA_EDIT_Y + _EXTRA_EDIT_H + _ui_v(26) _DESC_H = max(1, int(round(_ui_v(190) * 0.7))) _REFRESH_SHEET_CHK_Y = _DESC_Y + _DESC_H + _ui_v(12) _REFRESH_SHEET_CHK_H = _LBL_H _BTN_Y = _REFRESH_SHEET_CHK_Y + _REFRESH_SHEET_CHK_H + _GAP_S _ACTION_BTN_W = 90 _ACTION_BTN_GAP = _ui_v(8) _OK_BTN_X = _DLG_W - _M - _ACTION_BTN_W * 2 - _ACTION_BTN_GAP _CANCEL_BTN_X = _OK_BTN_X + _ACTION_BTN_W + _ACTION_BTN_GAP _DELETE_BTN_X = _M + _ACTION_BTN_W + _ACTION_BTN_GAP _REFRESH_SHEET_CHK_W = _OK_BTN_X - _M - _ACTION_BTN_GAP _DLG_H = _BTN_Y + _BTN_H_MAIN + _M # Вкладка «Глобальные»: флаги как в оркестраторе collect_pack. GLOBAL_FLAG_MARK_ON = u"☑ " GLOBAL_FLAG_MARK_OFF = u"❌ " GLOBAL_BOOL_FLAG_SPECS = ( (u"MERGE_XML_CONVERT_TO_NUMBERS", u"MERGE_XML_CONVERT_TO_NUMBERS"), (u"MERGE_SOURCE_VIEW_SUBFOLDERS", u"MERGE_SOURCE_VIEW_SUBFOLDERS"), (u"MERGE_DEBUG", u"MERGE_DEBUG"), (u"MERGE_DEBUG_CONSOLE_LOG_TO_WORKSHEET", u"MERGE_DEBUG_CONSOLE_LOG_TO_WORKSHEET"), (u"Автообрезка_листов", u"MERGE_COPY_AUTO_TRIM"), (u"MERGE_PASTE_FORMATS", u"MERGE_PASTE_FORMATS"), (u"Автофильтр_результата", u"MERGE_RESULT_AUTOFILTER"), (u"Закрепить_заголовок", u"MERGE_FREEZE_HEADER"), (u"MERGE_CONFIRM_DELETION_OF_SHEETS", u"MERGE_CONFIRM_DELETION_OF_SHEETS"), ) _GLOBAL_FMT_GAP = _ui_v(8) _GLOBAL_HALF_W = (_FIELD_W - _GLOBAL_FMT_GAP) // 2 _GLOBAL_NUM_X = _M + _GLOBAL_HALF_W + _GLOBAL_FMT_GAP _GLOBAL_FLAGS_LB_H = _ui_v(118) _GLOBAL_FLAG_HINT_H = _ui_v(44) _FALLBACK_PP_RANGE_CHOICES = [ u"авто_высота", u"авто_ширина", u"автофильтр", u"высота_строки", u"градиент", u"группировка_по_столбцу", u"заголовок_плюс_высота", u"закрепить_заголовок", u"зебра_диапазон", u"сортировка", u"раскрасить_блоки", u"конкатенация_столбцов", u"левое_выравнивание", u"отступ", u"перенос", u"перенос_и_авто_высота", u"применить_формулу", u"удаление_строк", u"сброс_стрипов", u"сетка", u"стиль_печати", u"толстая_сетка", u"тонкая_сетка", u"удалить_столбцы", u"подсветка_по_порогу", u"подкрасить_пороги", u"формат_даты", u"формат_деньги", u"формат_столбцы", u"ширина_столбцов", u"шрифт", u"заполнение_вниз", u"заполнение_вниз_вычислить", u"копировать_значения", u"замена_значений", u"текстовые_операции", u"переименовать_лист", u"переименовать_столбцы", u"переставить_столбцы", u"количество_значений", u"копировать_лист", u"сводная_таблица", ] _FALLBACK_PP_ROW_CHOICES = [ u"высота_строки", u"серые_служебные", u"полосы_по_пути", u"чередующиеся_границы", u"копировать_формат_заголовка", u"подсветка_по_заголовку", u"цвет_текста_по_значению", u"жирный_по_пути", u"преобразовать_числа", ] _FALLBACK_PP_XML_CHOICES = [ u"сетка", u"тонкая_сетка", u"толстая_сетка", u"заголовок_плюс_высота", u"перенос", u"перенос_и_авто_высота", u"авто_высота", u"авто_ширина", u"высота_строки", u"левое_выравнивание", u"отступ", u"шрифт", u"зебра_диапазон", u"формат_деньги", u"формат_даты", u"формат_столбцы", u"применить_формулу", u"удалить_столбцы", u"конкатенация_столбцов", u"замена_значений", u"текстовые_операции", u"заполнение_вниз", u"сортировка", u"переименовать_лист", u"переименовать_столбцы", u"переставить_столбцы", u"копировать_лист", u"закрепить_заголовок", u"автофильтр", u"сводная_таблица", ] _FALLBACK_PP_PLUGIN_REST = ( u"JSON в C: [{\"v\":1,\"fn\":\"функция_плагин\",\"ref\":\"functions_pp.py#имя\"," u"\"extra\":\"…\",\"sheet\":\"Лист\"}]; D — extra, если не в JSON", u'[{"v":1,"fn":"функция_плагин","ref":"functions_pp.py#pp_range_zagotovka","sheet":"Сводка"}]', ) _FALLBACK_FINAL_CHOICES = [ u"удаление_листов", u"скрытие_листов", u"только_значения", u"заголовок_плюс_высота", u"вертикаль_центр", u"зебра_диапазон", u"сортировка", u"раскрасить_блоки", u"сетка", u"тонкая_сетка", u"толстая_сетка", u"удалить_столбцы", u"конкатенация_столбцов", u"применить_формулу", u"количество_значений", u"копировать_лист", u"замена_значений", u"текстовые_операции", u"переименовать_лист", u"переименовать_столбцы", u"переставить_столбцы", ] PLUGIN_FUNCTION_KEY = u"функция_плагин" _PLUGIN_D_LBL_Y = _EXTRA_EDIT_Y + _EXTRA_EDIT_H + _GAP_S _PLUGIN_D_EDIT_Y = _PLUGIN_D_LBL_Y + _LBL_H _PLUGIN_DESC_OFFSET = _LBL_H + _EXTRA_EDIT_H + _GAP_S _DESC_H_PLUGIN = max(_ui_v(72), _DESC_H - _PLUGIN_DESC_OFFSET) _FALLBACK_FINAL_REST_HINTS = { PLUGIN_FUNCTION_KEY: ( u"JSON в C: [{\"v\":1,\"fn\":\"функция_плагин\",\"ref\":\"functions_final.py#имя\"," u"\"extra\":\"…\",\"sheet\":\"Лист\"}]; D — extra, если не в JSON", u'[{"v":1,"fn":"функция_плагин","ref":"functions_final.py#pp_range_zagotovka"}]', ), u"удаление_листов": ( u"имена/шаблоны (*Отчет*); опционально filter — лямбда name→bool (санация);\n" u"пусто — служебные по умолчанию; _Первый_; _Последний_; _Последний_мусорный_", u'[{"v":1,"fn":"удаление_листов","sheets":["*Отчет*"],' u'"filter":"lambda name: sheet_age_days(name) is not None and sheet_age_days(name) <= 3"}]', ), u"скрытие_листов": ( u"имена/шаблоны; опционально filter (как у удаления_листов); пусто — служебные;\n" u"_Первый_; _Последний_; _Последний_мусорный_", u'[{"v":1,"fn":"скрытие_листов","sheets":["Сбор_книг_лог*"]}]', ), u"только_значения": ( u"имена листов через запятую или ; — только значения; " u"лист со сводной — inplace (без нового листа)", u"Сводная", ), u"заголовок_плюс_высота": ( u"как в постобработке: «лист | +13 center-center ; …»; пусто — +12,7 мм center/center на всех", u"Сводная | +13 center-center ; Все | +8 center/bottom", ), u"вертикаль_центр": ( u"вертикальное выравнивание по центру на строках данных (заголовок не трогается); " u"C — список листов; пусто — пропуск", u"Сводная_1", ), u"зебра_диапазон": ( u"имя листа (или несколько через , или ;) | роль:заливка/шрифт — как у постобработки «зебра_диапазон»", u"Итог|header:excel_header/белый; even:голубой/синий; odd:белый/синий", ), u"сортировка": ( u"«лист | ключи» или «лист: ключи»; задания через ; (как в постобработке)", u"Сводная | Сумма -> -, Дата -> + ; Orders | Сумма -> -", ), u"раскрасить_блоки": ( u"«лист | столбцы_ключа -> цвета»; блоки через ;. " u"Цвета: имя или #hex; несколько — через %. " u"Сортировка: /+ или /asc — по возрастанию, /- или /убыв — по убыванию; " u"без суффикса — без сортировки; !граница — контур блоков", u"Сводная | Отдел -> голубой%белый/+ ; Orders | A, B -> #E2EFDA/-", ), u"раскрасить": ( u"алиас «раскрасить_блоки»", u"Сводная | Отдел -> голубой", ), u"сетка": ( u"как в постобработке: «толщина/цвет» или «лист | 25/#CCCCCC ; …»; пусто — тонкая серая на всех", u"Сводная | 25/#CCCCCC ; Orders : толстая/темныйсиний", ), u"тонкая_сетка": ( u"список листов через запятую или ; (пусто — все листы)", u"Сводная, Orders", ), u"толстая_сетка": ( u"список листов через запятую или ; (пусто — все листы)", u"Сводная, Orders", ), u"количество_значений": ( u"JSON: new_column, key_columns, trim, case_sensitive — как в постобработке", u'[{"v":1,"fn":"количество_значений","new_column":"Количество","key_columns":["ФИО"]}]', ), u"копировать_лист": ( u"JSON: source_sheet → dest_sheet, полная копия вкладки.\n" u"Для ODS (xml_excel_ods) можно ускорить: columns[] + skip_empty=true — копировать только нужные столбцы и пропускать пустые строки.", u'[{"v":1,"fn":"копировать_лист","source_sheet":"Шаблон","dest_sheet":"Копия","columns":["ФИО","Отдел"],"skip_empty":true,"header_row":1}]', ), u"удалить_столбцы": ( u"markers: подстроки/имена, индексы 1-based, буквы A/C; смесь через запятую", u"#Путь,3,A,Коммент*", ), u"конкатенация_столбцов": ( u"имя_нового_столбца, разделитель, индексы 1-based; без разделителя — индексы", u"Полный_Код,|,1,3,5", ), u"применить_формулу": ( u"имя_столбца=формула Calc; {row_id} — первая строка данных", u"Итого=E{row_id}+F{row_id}", ), u"замена_значений": ( u"JSON: columns + find + replace; кнопка «Параметры…»", u'[{"v":1,"fn":"замена_значений","columns":["ФИО"],"find":["ООО"],"replace":["ОБЩЕСТВО"]}]', ), u"переименовать_лист": ( u"новое имя листа; при конфликте — суффикс _2, _3, …", u"Итоговый_отчёт", ), u"переименовать_столбцы": ( u"JSON: sheet + mappings (Старое=Новое); кнопка «Параметры…»", u'[{"v":1,"fn":"переименовать_столбцы","sheet":"Заказы",' u'"mappings":[{"old":"Сумма","new":"Итого_сумма"}]}]', ), u"переставить_столбцы": ( u"JSON: sheet (обязателен), columns, position (_начало_|_конец_|_перед_|_после_), " u"relative_column для _перед_/_после_; copy=true + new_names — копии столбцов", u'[{"v":1,"fn":"переставить_столбцы","sheet":"Заказы","columns":["C"],' u'"position":"_конец_","copy":true,"new_names":["C_копия"]}]', ), } _VLOOKUP_COL_HEADERS = ( u"Левая_Таблица", u"Правая_Таблица", u"Ключ_сравнения", u"Столбцы_для_извлечения", u"Цвет_добавленных_данных", ) _FALLBACK_PP_RANGE_REST_HINTS = { u"сетка": ( u"толщина/цвет — тонкая|толстая|число / имя цвета или hex; " u"по листам: «лист | 25/#CCCCCC ; …» (разделитель |, : или /); пусто = тонкая серая", u"Сводная | 25/#CCCCCC ; Orders : толстая/темныйсиний", ), u"тонкая_сетка": ( u"список листов через запятую или ; (пусто — все листы)", u"Сводная, Orders", ), u"толстая_сетка": ( u"список листов через запятую или ; (пусто — все листы)", u"Сводная, Orders", ), u"заголовок_плюс_высота": ( u"«лист | +13 center-center» или только параметры (все листы); мм — число без единиц; " u"выравнивание: left/center/right (Л/Ц/П) и top/center/bottom (В/Ц/Н)", u"Сводная | +13 center-center ; 2 | +8 left-top", ), u"перенос": (u"пусто = включить; No/Нет — выключить перенос", u"Нет"), u"перенос_и_авто_высота": (u"как у «перенос»: пусто = включить; No/Нет — выключить", u"Нет"), u"авто_высота": (u"автоподбор высоты строк данных (OptimalHeight)", u""), u"авто_ширина": (u"автоподбор ширины столбцов диапазона (OptimalWidth)", u""), u"высота_строки": ( u"пусто — все строки данных, 5 мм; «6» — все строки; «2,3 / 6» (или ->, =); «0» — скрыть; " u"«6 мм» тоже допускается", u"2,3,4 / 6", ), u"левое_выравнивание": (u"не используется", u""), u"отступ": ( u"[left|center|right], число_шагов [, столбцы]; пусто = left, 1, все", u"right,1,Сумма", ), u"шрифт": ( u"имя;размер_данных;размер_заголовка (или через запятую); «-» = не менять", u"Arial;11;12", ), u"зебра_диапазон": ( u"роль:заливка/шрифт через «;» или «,» — header/заголовок, even/четные, odd/нечетные", u"header:excel_header/белый, even:голубой/синий, odd:белый/синий", ), u"сортировка": ( u"«лист | ключи» или «лист: ключи»; задания через ;. " u"Без листа — ключи для всех листов. Ключ: колонка -> +/-", u"Сводная | Сумма -> -, Дата -> + ; Orders | Сумма -> -", ), u"раскрасить_блоки": ( u"«лист | столбцы_ключа -> цвета»; блоки через ;. " u"Без листа — для текущего листа. Цвета: имя или #hex; несколько — через %. " u"Сортировка: /+ или /asc — по возрастанию, /- или /убыв — по убыванию; " u"без суффикса — без сортировки; !граница — контур блоков", u"Отдел, Город -> голубой%белый%серый/+!граница", ), u"раскрасить": ( u"алиас «раскрасить_блоки»", u"Отдел -> голубой", ), u"формат_деньги": ( u"лист, формат (пусто = глобальный), столбцы, маркеры заголовка", u'{"sheet":"Отчет","format":"# ##0,00","columns":"Сумма,3"}', ), u"формат_даты": ( u"лист, формат (пусто = глобальный), столбцы, маркеры заголовка", u'{"sheet":"Отчет","format":"DD.MM.YYYY","markers":"дата,время"}', ), u"формат_столбцы": ( u"столбец: имя, номер, буква, список через запятую, Все/*; формат — шаблон (пусто = не менять)", u"ФИО, Отдел,# ##0,00", ), u"подсветка_по_порогу": ( u"столбцы, порог min/max, цвет заливки; JSON: font_color, bold, italic", u'{"columns":["Итого"],"threshold_min":0,"threshold_max":1000,"color":"светло_красный"}', ), u"подкрасить_пороги": ( u"алиас «подсветка_по_порогу»", u'{"columns":["Итого"],"threshold_min":0,"threshold_max":1000,"color":"светло_красный"}', ), u"градиент": ( u"маркер столбца, цвет min, цвет max; JSON: whole_row, sort, sort_dir (по_возр/по_убыв)", u"сумм -> зеленый -> красный", ), u"удалить_столбцы": ( u"markers: подстроки/имена, индексы 1-based, буквы A/C; смесь через запятую", u"#Путь,3,A,Коммент*", ), u"конкатенация_столбцов": ( u"имя_нового_столбца, разделитель, индексы 1-based (1=A); без разделителя — индексы", u"Полный_Код,|,1,3,5", ), u"применить_формулу": ( u"имя_столбца=формула Calc; {row_id} — первая строка данных (1-based)", u"Итого=E{row_id}+F{row_id}", ), u"удаление_строк": ( u"столбцы (1,A,ФИО) или формула пустой строки: ИСТИНА → удалить", u"Табельный_номер", ), u"сброс_стрипов": (u"не используется", u""), u"группировка_по_столбцу": (u"подстрока в заголовке столбца группировки", u"группа"), u"закрепить_заголовок": (u"не используется", u""), u"ширина_столбцов": ( u"пусто — все столбцы, 30 мм; «30» — все столбцы; «1,2,3 / 30» (или ->, =); «0» — скрыть; " u"«30 мм» тоже допускается", u"1,2,3 / 30", ), u"автофильтр": ( u"JSON: sheets — список листов; без sheets — все листы. " u"В Постобработка_xml (xml_excel_ods) — UNO-добивка после reopen", u'[{"v":1,"fn":"автофильтр","sheets":["Заказы"]}]', ), u"стиль_печати": ( u"ориентация (landscape/portrait), вписать в N страниц по ширине", u"landscape,1", ), u"заполнение_вниз": ( u"столбцы: номер (1-based), буква A или имя заголовка; через , или ;", u"ФИО;Отдел;3", ), u"заполнение_вниз_вычислить": ( u"JSON: columns + rules (column, formula, expand_to_right); кнопка «Параметры…»", u'[{"v":1,"fn":"заполнение_вниз_вычислить","columns":["A"],"rules":[{"column":"A","formula":"=A{row-1}"}]}]', ), u"копировать_значения": ( u"столбцы через , или ; — номер (1-based), буква A или имя заголовка; пусто — весь лист", u"Сумма,Количество", ), u"замена_значений": ( u"JSON: columns + find + replace (1 или N), флаги case_insensitive/squeeze_spaces; кнопка «Параметры…»", u'[{"v":1,"fn":"замена_значений","columns":["ФИО"],"find":["ООО"],"replace":["ОБЩЕСТВО"],"case_insensitive":true,"squeeze_spaces":true}]', ), u"текстовые_операции": ( u"JSON: columns + ops[] (trim/collapse_ws/case/lang_homoglyphs/…); кнопка «Параметры…»", u'[{"v":1,"fn":"текстовые_операции","columns":["ФИО"],"ops":[{"op":"collapse_ws"},{"op":"case","mode":"proper"}]}]', ), u"переименовать_лист": ( u"новое имя листа; при конфликте — суффикс _2, _3, …", u"Итоговый_отчёт", ), u"переименовать_столбцы": ( u"JSON: sheet + mappings (Старое=Новое); кнопка «Параметры…»", u'[{"v":1,"fn":"переименовать_столбцы","sheet":"Заказы",' u'"mappings":[{"old":"Сумма","new":"Итого_сумма"}]}]', ), u"переставить_столбцы": ( u"JSON: sheet (обязателен), columns, position (_начало_|_конец_|_перед_|_после_), " u"relative_column для _перед_/_после_; copy=true + new_names — копии столбцов", u'[{"v":1,"fn":"переставить_столбцы","sheet":"Заказы","columns":["C"],' u'"position":"_конец_","copy":true,"new_names":["C_копия"]}]', ), u"количество_значений": ( u"JSON: new_column, key_columns, trim, case_sensitive — см. визард «Параметры…»", u'[{"v":1,"fn":"количество_значений","new_column":"Количество","key_columns":["ФИО"]}]', ), u"копировать_лист": ( u"JSON: source_sheet → dest_sheet, полная копия вкладки", u'[{"v":1,"fn":"копировать_лист","source_sheet":"Шаблон","dest_sheet":"Копия"}]', ), u"сводная_таблица": ( u"JSON (кнопка «Параметры»). source_sheet — только для указанного листа результата (* — шаблон).", u"{\"v\":1,\"source_sheet\":\"Merge\",\"sheet_name\":\"Сводная\",\"as_values\":false,\"row_fields\":[\"Отдел\"],\"column_fields\":[],\"filter_fields\":[],\"data_fields\":[{\"field\":\"Сумма\",\"function\":\"SUM\"}]}", ), PLUGIN_FUNCTION_KEY: _FALLBACK_PP_PLUGIN_REST, } _FALLBACK_PP_XML_REST_HINTS = { key: _FALLBACK_PP_RANGE_REST_HINTS[key] for key in _FALLBACK_PP_XML_CHOICES if key in _FALLBACK_PP_RANGE_REST_HINTS } _FALLBACK_PP_ROW_REST_HINTS = { u"высота_строки": ( u"пусто — 5 мм на строку; «6» — 6 мм; «2,3 / 6» (или ->, =) — только эти строки (1-based); «0» — скрыть; " u"«6 мм» тоже допускается", u"2,3,4 / 6", ), u"серые_служебные": (u"не используется", u""), u"полосы_по_пути": (u"не используется", u""), u"чередующиеся_границы": (u"не используется", u""), u"копировать_формат_заголовка": (u"не используется", u""), u"подсветка_по_заголовку": (u"не используется", u""), u"цвет_текста_по_значению": (u"подстрока заголовка столбца-источника", u"статус"), u"жирный_по_пути": (u"не используется (подстрока в коде макроса)", u""), u"преобразовать_числа": ( u"колонки (опционально): индексы 0,2,5 или имена Сумма,Количество", u"", ), PLUGIN_FUNCTION_KEY: ( u"C — functions_pp.py#имя или Python lambda/def; D — доп. аргументы через запятую", u"functions_pp.py#pp_row_zagotovka", ), } MERGE_PARAM_SHEET_NAME = u"Параметры_Объединения" MERGE_PARAM_SHEET_MAX_ROWS = 200 P_MERGE_COMMENT = u"Комментарий" P_MERGE_VERSION = u"Версия" _PARAM_DV_SHEET_NAME = u"_Визард_Списки" _PARAM_DV_INLINE_MAX = 248 _PARAM_DV_LIST_CACHE = {} _PARAM_DV_NEXT_COL = 0 _COLLECT = None _LM_LIB = None _PP_PLUGIN_SIG_RANGE = ( "doc", "sheet", "data_range", "header_row_range", ) _PP_PLUGIN_SIG_ROW = ( "doc", "sheet", "data_row_range", "header_row_range", "row_index", ) _PP_PLUGIN_SIG_FINAL = ( "doc", "sheets", "data_ranges", "header_row_ranges", ) VALUE_HINTS = { u"На один лист": ( u"Все данные собираются на один лист результата (обычно «Merge»).\n" u"Доступны служебные колонки #Путь и #ДатаВремяФайла." ), u"На разные листы": ( u"Каждый источник/лист — отдельная вкладка (_N в имени).\n" u"Служебный лист «Индексы_Источников»." ), u"Копирование листов": ( u"Целые листы копируются как вкладки (как «Копировать лист»).\n" u"Без встроенного оформления; постобработка по блоку параметров\n" u"(Начало_Строка, Начало_Столбец, Число_Строк, Число_Столбцов, Строка_Заголовков)\n" u"или по значащей области листа, если границы не заданы.\n" u"При конфликте имён: N_имя_листа (N — порядковый номер совпадения имени листа).\n" u"Способ переноса: по умолчанию По_API (UNO). Для xml_excel_ods выберите в поле " u"«Способ_переноса (C)» в визарде или задайте отдельную строку «Способ_переноса».\n" u"Служебные #Путь / #ДатаВремяФайла не добавляются." ), u"Текущие листы": ( u"Без копирования и объединения: вкладки текущей книги (эта_книга / ThisWorkbook)\n" u"сразу идут в постобработку и финальную обработку.\n" u"В «Файлы-Источники» — только маркер текущей книги " u"(эта_книга, Эта-книга, ThisWorkbook, This_Workbook, …).\n" u"«Листы» — какие вкладки обработать. Предварительное удаление листов отключено.\n" u"Способ_переноса и столбцы/диапазоны сбора не используются." ), u"Вовлечь листы": ( u"Legacy-имя режима «Текущие листы». Без копирования: вкладки эта_книга → постобработка/финал." ), u"По_API": ( u"Перенос через UNO API (пакеты и построчно) — поведение по умолчанию." ), u"Буфер_по_заголовкам": ( u"Копирование через буфер обмена по столбцам с матчингом заголовков." ), u"Буфер_по_позиции": ( u"Копирование прямоугольника через буфер без матчинга; заголовки — при первой записи." ), u"Не_выводить": u"Служебная колонка не добавляется.", u"Коротко": u"Короткий вариант (путь или дата без времени).", u"Длинно": u"Полный вариант (полный путь или дата+время).", u"Да": u"Включить (автофильтр, закрепление заголовка). Допустимо: +/-, true/false, yes/no, истина/ложь.", u"Нет": u"Отключить. Регистр не важен.", u"Статусная_строка": u"Прогресс в строке состояния Calc (по умолчанию).", u"Диалог": u"Отдельное окно с полосой прогресса на этапе 2.", } WIZARD_HINTS = { P_MERGE_COMMENT: ( u"Описание сценария для человека (макрос не читает).\n" u"Пример: «Слияние отчётов филиалов за январь, один лист Merge»." ), u"Файлы-Источники": ( u"Пути к книгам-источникам: B — первый файл, C — второй, D — третий…\n" u"Допустимы маски: /data/отчёт_*.xlsx , *source_* , *source_*.xlsx (регистронезависимо).\n" u"Для .xls/.ods используйте *source_* (маска *.xlsx не включает .xls).\n" u"MERGE_SOURCE_VIEW_SUBFOLDERS=Да — рекурсивно во всех подпапках стартовой директории.\n" u"MERGE_SOURCE_EXCLUDE_MASK — доп. исключения (по умолчанию --*); имена ~* пропускаются всегда.\n" u"Маркер текущей книги: эта_книга / Эта-книга / этакнига / ThisWorkbook / This_Workbook / current…\n" u"Визард добавляет путь в следующий свободный столбец строки.\n" u"Примеры:\n" u" /home/user/source_01.xlsx\n" u" /home/user/sources/*source_*.xlsx\n" u" Эта_книга" ), u"Листы": ( u"Фильтр листов на каждый файл (B,C,D… — как у «Файлы-Источники»).\n" u"Колонка B — шаблоны через запятую (text_match): МТ*, Отчет*, Все, *, 1.\n" u"Колонка C (кнопка «Параметры…») — опциональный JSON-фильтр (как у «Листы_не_удалять»):\n" u' {"v":1,"filter":"lambda name: sheet_age_days(name) is not None and sheet_age_days(name) <= 3"}\n' u"Лямбда получает имя листа из отобранных по B; True — включить в обработку.\n" u"Если C — не JSON/lambda, это шаблоны для 2-го файла (как раньше); D — для 3-го и т.д.\n" u"В режиме «Текущие листы» — какие вкладки текущей книги обработать (без копирования).\n" u"В одной ячейке — список через , или ; (без смешения типов).\n" u"Примеры B:\n" u" Отчет* — листы, имя начинается с «Отчет»\n" u" *2024 — заканчиваются на 2024\n" u" 1 — первый лист книги\n" u" Все — все листы" ), u"Столбцы": ( u"Фильтр столбцов (B,C,D… по файлам). Пусто или «Все» — все столбцы.\n" u"Номер (1=A), буква (C), имя заголовка (ФИО), шаблон (Сумма*).\n" u"Примеры:\n" u" ФИО;Табельный_номер;Отдел\n" u" 1,3,6\n" u" A,C,F" ), u"Начало_Строка": ( u"Первая строка данных (1-based). Пусто, 0 или отрицательное — 1.\n" u"Сбор строк начинается с этой строки.\n" u"Примеры: 2 1" ), u"Начало_Столбец": ( u"Первый столбец блока: номер (1) или буква (A).\n" u"Примеры: 1 A B" ), u"Число_Строк": ( u"Сколько строк данных копировать. Пусто — до пустой ячейки в «Начало_Столбец».\n" u"Примеры: (пусто) 10 100" ), u"Число_Столбцов": ( u"Лимит столбцов при режиме «Все». Пусто — до пустого заголовка.\n" u"Примеры: (пусто) 6 12" ), u"Строка_Заголовков": ( u"Строка с именами столбцов (1-based). Пусто — как «Начало_Строка».\n" u"0 или отрицательное — заголовка нет (Колонка_A, Колонка_B…).\n" u"Примеры: 2 1 0" ), u"Режим": ( u"Способ объединения данных на листе результата.\n" u"Выберите значение в колонке B — подробности появятся ниже.\n" u"«Текущие листы» — без копирования: существующие вкладки эта_книга → постобработка/финал;\n" u"предварительное удаление листов не выполняется.\n" u"Для режимов сбора способ переноса задаётся в колонке C " u"той же строки (или отдельной строкой «Способ_переноса» — она имеет приоритет)." ), u"Источник_в_первой_колонке": ( u"Служебная колонка «#Путь».\n" u"Не_выводить / Коротко / Длинно.\n" u"Только для «На один лист» и «На разные листы»; в «Копирование листов» / «Текущие листы» не используется." ), u"Дата_источника_во_второй_колонке": ( u"Служебная колонка «#ДатаВремяФайла».\n" u"Не_выводить / Коротко (дата) / Длинно (дата+время).\n" u"Только для «На один лист» и «На разные листы»; в «Копирование листов» / «Текущие листы» не используется." ), u"Дата_источника_во_второй__колонке": ( u"(устаревшее имя параметра — используйте «Дата_источника_во_второй_колонке»)\n" u"Служебная колонка «#ДатаВремяФайла»." ), u"Способ_переноса": ( u"Как переносить данные источника в результат.\n" u"Обычно задаётся в колонке C строки «Режим»; отдельная строка с этим именем " u"сохранена для совместимости и имеет приоритет над C.\n" u"Для «Копирование листов» поле C в визарде доступно так же, как для других режимов.\n" u"В режиме «Текущие листы» не используется (переноса нет).\n" u"По_API (по умолчанию) — текущий механизм (пакеты getDataArray/setDataArray + построчно при необходимости).\n" u"Буфер_по_заголовкам — .uno:Copy + спецвставка «только значения» по столбцам; " u"столбец результата по заголовку. Форматы — только при MERGE_PASTE_FORMATS=Да.\n" u"Буфер_по_позиции — копирование прямоугольника данных в буфер без матчинга заголовков " u"(тоже только значения; форматы — MERGE_PASTE_FORMATS); " u"строка заголовков копируется один раз при первой записи на лист.\n" u"xml_excel_ods — прямой перенос через работу с файлами (.xlsx/.xlsm/.xls/.ods): " u"книга результата сохраняется и закрывается, файл результата обновляется на диске и открывается снова." ), u"MERGE_PASTE_FORMATS": ( u"Только для «Способ_переноса» = Буфер_по_заголовкам / Буфер_по_позиции.\n" u"Нет (по умолчанию) — спецвставка только значений (InsertContents SVD).\n" u"Да — поверх вставленных значений ещё спецвставка форматов (InsertContents T / HARDATTR|STYLES)." ), u"Папка_результата": ( u"Каталог для файла результата в режиме xml_excel_ods без подмены открытой книги.\n" u"Абсолютный путь или относительно папки книги с параметрами.\n" u"Если не задано — используется системная временная папка.\n" u"Туда копируется книга как «имя-result.ext»; исходная книга остаётся открытой.\n" u"В конце показывается путь к готовому файлу." ), u"MERGE_XML_CONVERT_TO_NUMBERS": ( u"Да (по умолчанию) — текст «700», «1 000 000,00», «01.02.2024» превращается в число/дату в результате.\n" u"При «Способ_переноса» = xml_excel_ods — при чтении источников из файла; " u"для «Копирование листов» — отдельный проход по скопированным листам.\n" u"При По_API / Буфер_по_заголовкам / Буфер_по_позиции — проход по листу результата после копирования.\n" u"Столбец обрабатывается, если ≥3 строк данных распознаны как дата/время или число " u"(пробел/апостроф между разрядами, дробная , или .).\n" u"Нет — сохранять как текст (в т.ч. даты-строки)." ), u"MERGE_XML_DATETIME_FORMATS": ( u"Список допустимых форматов даты/времени для преобразования текста → date/datetime " u"(через запятую). Используется при MERGE_XML_CONVERT_TO_NUMBERS=Да " u"(xml_excel_ods и UNO-сбор).\n" u"Если пусто — базовые форматы (точка/дефис, ISO) плюс дополнения по локали LibreOffice " u"(ru: DD/MM, 01.фев.2024, 1 февраля 2024; en-US: MM/DD).\n" u"Допускаются кириллические токены: ДД.ММ.ГГГГ, ДД/ММ/ГГГГ, ДД.МММ.ГГГГ и т.д.\n" u"Примеры:\n" u" DD.MM.YYYY, DD.MM.YY, YYYY-MM-DD, YY-MM-DD\n" u" DD.MM.YYYY HH:MM(:SS), DD.MM.YYYYTHH:MM(:SS)\n" u" DD/MM/YYYY, DD.MMM.YYYY, D MMMM YYYY, MM/DD/YYYY" ), u"MERGE_SOURCE_VIEW_SUBFOLDERS": ( u"Да (по умолчанию) — при маске в «Файлы-Источники» искать совпадения " u"в стартовой папке и во всех её подпапках.\n" u"Нет — только в каталоге из пути маски (без рекурсии).\n" u"Синонимы Да/Нет: yes/no, 1/0, true/false (без учёта регистра)." ), u"MERGE_SOURCE_EXCLUDE_MASK": ( u"Дополнительные маски исключения для имён файлов (через запятую), " u"после основной маски отбора.\n" u"По умолчанию: --*\n" u"Файлы с именем, начинающимся на ~, пропускаются всегда.\n" u"Совпадение регистронезависимое.\n" u"Пример: --*,*.tmp,~$*" ), u"Листы_не_удалять": ( u"Листы, не удаляемые при очистке книги результата перед сбором.\n" u"Колонка B — шаблоны через запятую (text_match): *Отчет*, Отчет*, Справка_макроса.\n" u"Пусто — список по умолчанию из макроса.\n" u"«*» / «Все» / «All» без фильтра в C — не удалять никакие листы.\n" u"Колонка C (кнопка «Параметры…») — опциональный JSON:\n" u' {"v":1,"filter":"lambda name: sheet_age_days(name) is not None and sheet_age_days(name) <= 3"}\n' u"Лямбда получает имя листа из отобранных по B; True — сохранить. Код санируется.\n" u"Листы Параметры_Объединения* и _Визард_Списки защищены всегда.\n" u"В режиме «Текущие листы» предварительная очистка всегда отключена." ), u"Пропуск_строк_источника": ( u"Не копировать «пустые» строки при сборе.\n" u"Колонка B — «смотри в С»; правила — JSON в C (кнопка «Параметры…»).\n" u"sheet — имя листа *источника* (не результата); пусто = все листы файла.\n" u"columns — номера/буквы/заголовки: строка копируется, если хотя бы один не пуст.\n" u"Файл источника не сохраняется (изменения только в скрытой копии).\n" u'Пример: [{"v":1,"fn":"пропуск_строк_источника","sheet":"Заказы","columns":["1"]}]' ), u"Автофильтр_результата": ( u"Автофильтр на листе результата после сбора.\n" u"Колонка B — «смотри в С»; настройки листов — JSON в колонке C (кнопка «Параметры…»).\n" u"Пустой JSON / все листы — автофильтр на каждом листе результата." ), u"Закрепить_заголовок": ( u"Закрепить строку заголовков (freeze panes) на листе результата.\n" u"Колонка B — «смотри в С»; настройки листов — JSON в колонке C (кнопка «Параметры…»).\n" u"Пустой JSON / все листы — на всех листах результата." ), u"Отображение_прогресса": ( u"Как показывать прогресс на этапе 2.\n" u"Диалог (по умолчанию) или Статусная_строка.\n" u"Диалог: сводка + «Запуск», затем прогресс + «Прервать»." ), u"MERGE_DEBUG": ( u"Подробный отладочный вывод в консоль (этап, память, таймер).\n" u"Да — включает debug-флаги во всех библиотеках макроса.\n" u"По умолчанию Нет." ), u"MERGE_DEBUG_CONSOLE_LOG_TO_WORKSHEET": ( u"Писать на лист «Сбор_книг_лог» всё, что идёт в консоль (Время | Сообщение),\n" u"вместо обычного журнала сбора. Рекомендуется вместе с MERGE_DEBUG=Да.\n" u"По умолчанию Нет." ), u"Ячейка_В_Столбец": ( u"Вертикальный список (имя в A повторяется). B,C,D… — по файлам.\n" u"Legacy: «столбец:строка -> имя_колонки» (1-based).\n" u"JSON в колонке C (кнопка «Параметры…»):\n" u' [{"col":"A","row":1,"column":"Филиал","sheet":"Merge",' u'"source_sheet":"Отчет*"}]\n' u"sheet — лист результата (пусто = все); source_sheet — фильтр листа " u"источника (*, список через запятую; пусто = все)." ), u"удаление_верхних_строк": ( u"После сбора, до Постобработка_xml: удалить N верхних строк на листе результата.\n" u"Колонка B — «смотри в С»; правила — JSON в C (кнопка «Параметры…»).\n" u"Имя листа: как после копирования («1_Заказы») или без префикса («Заказы») — оба варианта.\n" u"Порядок относительно переименовать_лист не важен: удаление всегда раньше rename.\n" u"При явном правиле для листа автообрезка (Автообрезка_листов) для него не выполняется." ), u"Автообрезка_листов": ( u"Только режим «Копирование листов».\n" u"Да (по умолчанию) — после копии обрезать строки до «Строка_Заголовков» " u"и промежуток до «Начало_Строка» (шапка оказывается в строке 1).\n" u"Нет — копировать лист целиком без автообрезки.\n" u"Явное «удаление_верхних_строк» работает независимо от этого флага." ), u"MERGE_CONFIRM_DELETION_OF_SHEETS": ( u"Запрашивать подтверждение перед удалением «лишних» листов на этапе 1 сбора.\n" u"Нет (по умолчанию) — удалять без запроса; Да — диалог подтверждения." ), u"Постобработка_Диапазон": ( u"Вертикальный список шагов постобработки диапазона (имя в A повторяется).\n" u"B — ключ функции из списка или «функция_плагин».\n" u"C — только JSON (кнопка «Параметры…»); D — rest плагина, если не в JSON.\n" u"Порядок шагов — сверху вниз на листе параметров.\n" u"Примеры C:\n" u' [{"v":1,"fn":"тонкая_сетка"}]\n' u' [{"v":1,"fn":"функция_плагин","ref":"functions_pp.py#pp_range_zagotovka","extra":"42","sheet":"Сводка"}]\n' u' [{"v":1,"fn":"заголовок_плюс_высота","height_mm":13,"h_align":"center","v_align":"center"}]' ), u"Постобработка_Строка": ( u"Вертикальный список шагов постобработки строки (имя в A повторяется).\n" u"B — ключ функции из списка или «функция_плагин».\n" u"C — JSON; D — rest плагина при необходимости.\n" u"Выполняется после всех шагов «Постобработка_Диапазон».\n" u'Пример: [{"v":1,"fn":"преобразовать_числа"}]' ), u"Постобработка_xml": ( u"Постобработка в файле — только для «Способ_переноса» = xml_excel_ods.\n" u"Вертикальный список (имя в A повторяется); B — функция из отдельного каталога;\n" u"C — JSON (кнопка «Параметры…»). Выполняется в файле после сбора, до reopen UNO.\n" u"Часть шагов (авто_ширина/высота, заголовок_плюс_высота, автофильтр, " u"закрепить_заголовок) — UNO-добивка после открытия книги.\n" u"Обычная «Постобработка_Диапазон» при xml_excel_ods — после открытия книги (UNO).\n" u'Пример: [{"v":1,"fn":"применить_формулу","column":"Итого","formula":"=D{row_id}*0.1"}]' ), u"ВПР": ( u"Операция LEFT OUTER JOIN между листами книги результата.\n" u"Строка в A: ВПР (или VLookup). Колонки B–F (подпись «Метка: значение» — " u"метка только подсказка, при выполнении отбрасывается):\n" u" B — Левая_Таблица: Лист|Начало_Строка|Начало_Столбец|Строка_Заголовков\n" u" C — Правая_Таблица: тот же формат (или JSON при «Сохранять как JSON»)\n" u" D — Ключ_сравнения: столбцы через , или раздельно\n" u" Ключ_сравнения_левый: … # Ключ_сравнения_правый: …\n" u" E — Столбцы_для_извлечения: имена столбцов правой таблицы\n" u" F — Цвет_добавленных_данных, Заполнять_дубли, Заполнитель_для_не_найдено (через , или ;)\n" u"JSON (§5.2): галочка в диалоге → только колонка C, массив [{\"fn\":\"впр\",…}].\n" u"ВПР выполняется между шагами «Постобработка_Диапазон»; " u"«Постобработка_Строка» — только после всех ВПР." ), u"Финальная_обработка": ( u"Шаги по всей книге перед диалогом «Завершить».\n" u"B — ключ функции (удаление_листов, скрытие_листов, функция_плагин…; " u"регистр в B не важен).\n" u"C — JSON; D — rest плагина, если не в JSON.\n" u"Примеры C:\n" u' [{"v":1,"fn":"удаление_листов"}]\n' u' [{"v":1,"fn":"функция_плагин","ref":"functions_final.py#pp_range_zagotovka","sheet":"Сводка"}]\n' u' [{"v":1,"fn":"заголовок_плюс_высота","height_mm":13,"sheet":"Сводная"}]' ), } P_MERGE_POSTPROCESS_RANGE = u"Постобработка_Диапазон" P_MERGE_POSTPROCESS_ROW = u"Постобработка_Строка" P_MERGE_POSTPROCESS_XML = u"Постобработка_xml" P_MERGE_CELL_TO_COLUMN = u"Ячейка_В_Столбец" _SCENARIO_01_COMMENT = ( u"Нагрузочный тест ВПР (уровень low); копирование листов «Заказы» и " u"«Справочник_цен» из vlookup_data_low_old.xlsx (~180 строк, ключ " u"Код_позиции). Режим xml_excel_ods: Удаление_верхних_строк → " u"Постобработка_xml (в т.ч. переименовать_лист) → ВПР → оформление." ) _WP_CREATE_DEFAULT_PRESET_NAME = u"— Шаблон по умолчанию (xml+ВПР) —" _WP_PRESETS_FILE = u"merge_param_presets.json" _WP_PRESETS_SUBDIR = u"collect_workbooks" _WP_PRESETS_JSON_VER = 1 _WP_EXAMPLE_PRESET_COUNT = 18 _WP_SCENARIO_COUNT = 9 _PARAM_VALUE_COLUMNS = 5 _PARAM_FONT_NAME = u"PT Sans" _PARAM_FONT_SIZE = 11 _PARAM_FILL_HEADER = 0xDCE4EE _PARAM_FILL_NAME = 0xF0F1F3 _PARAM_BORDER_COLOR = 0xB4B4B4 _PARAM_FILL_DISABLED = 0x666666 _PARAM_B_SEE_COLUMN_C = u"смотри в С" _PARAM_COL_WIDTHS = (8500, 9500, 9500, 9500, 9500, 9500) _DESC_GENERAL_INFO_SEPARATOR = u"---------Общая информация ---------" _PICK_SOURCE = None _INNER_BTN_W = 80 _INNER_BTN_H = 16 _INNER_BTN_GAP = 10 _INNER_CHK_H = 14 _INNER_FOOTER_RESERVE = _INNER_BTN_H + 4 + _INNER_CHK_H + 6 _INNER_GRID_DH = 420 _INNER_GRID_CONTROLS_H = 56 _INNER_GRID_LIST_GAP = 8 _INNER_LBL_W = 86 _INNER_LBL_GAP = 6 _INNER_FIELD_ROW_H = 22 _INNER_BLOCK_ALL_SHEETS_LABEL = u"(все_листы)" _SHEET_LIST_PANEL_FNS = ( u"тонкая_сетка", u"толстая_сетка", u"авто_высота", u"авто_ширина", u"левое_выравнивание", u"сброс_стрипов", u"закрепить_заголовок", u"автофильтр", u"вертикаль_центр", u"только_значения", u"удаление_листов", u"скрытие_листов", u"серые_служебные", u"полосы_по_пути", u"чередующиеся_границы", u"копировать_формат_заголовка", u"подсветка_по_заголовку", u"жирный_по_пути", ) _SHEET_LIST_PANEL_FN_CF = frozenset(x.casefold() for x in _SHEET_LIST_PANEL_FNS) _SHEET_LIST_SPECIAL_FNS = (u"удаление_листов", u"скрытие_листов") _SHEET_LIST_SPECIAL_TOKENS = ( u"_Первый_", u"_Последний_", u"_Последний_мусорный_", ) _HEADER_PLUS_HEIGHT_HORI_CHOICES = (u"left", u"center", u"right") _HEADER_PLUS_HEIGHT_VERT_CHOICES = (u"top", u"center", u"bottom") _SHEET_BLOCK_FIELD_GAP = 5 def _header_plus_height_color_choices(): """Именованные пресеты + hex для combo заливки/шрифта.""" out = [u""] seen = set() try: from libre_macros_lib import _LM_PP_ZEBRA_COLOR_ALIASES keys = sorted(_LM_PP_ZEBRA_COLOR_ALIASES.keys(), key=lambda x: unicode(x).casefold()) ki = 0 while ki < len(keys): key = unicode(keys[ki]) rgb = _LM_PP_ZEBRA_COLOR_ALIASES[key] sig = tuple(rgb) if sig not in seen: seen.add(sig) out.append(key) ki = ki + 1 except Exception: pass for hx in (u"#FFFFFF", u"#F2F2F2", u"#1F4E79", u"#4472C4", u"#FFC7CE"): if hx not in out: out.append(hx) return tuple(out) _SHEET_BLOCK_FORM_SCHEMAS = { u"удаление_верхних_строк": { "title": u"Удаление верхних строк", "hint": ( u"До Постобработка_xml удалить N верхних строк на листах результата.\n" u"Лист: «1_Заказы» или «Заказы» (префикс N_ учитывается).\n" u"Удаление всегда до переименовать_лист — порядок строк параметров не важен." ), "hint_lines": 4, "fields": ( {"id": "n", "label": u"N верхних строк", "default": u"1"}, ), }, u"пропуск_строк_источника": { "title": u"Пропуск строк источника", "hint": ( u"При сборе не копировать строки, где все указанные столбцы пусты.\n" u"Лист — имя листа *источника* (как в книге-источнике), не результата.\n" u"Пустой лист = правило для всех листов файла.\n" u"Столбцы: номера (1=A), буквы или имена заголовков через запятую.\n" u"Файл источника на диск не сохраняется." ), "hint_lines": 5, "fields": ( { "id": "columns", "label": u"Столбцы (непустота)", "default": u"1", }, ), }, u"Ячейка_В_Столбец": { "title": u"Ячейка → столбец", "hint": ( u"Ячейка на листе источника → новый столбец в результате.\n" u"Строка — 1-based; столбец — буква (A) или номер (1).\n" u"sheet — лист результата (пусто = все); source_sheet — фильтр листа " u"источника (Отчет*, список через запятую)." ), "hint_lines": 4, "fields": ( {"id": "col", "label": u"Столбец", "default": u"A"}, {"id": "row", "label": u"Строка", "default": u"1"}, {"id": "column", "label": u"Имя колонки", "default": u""}, {"id": "sheet", "label": u"Лист результата", "default": u""}, {"id": "source_sheet", "label": u"Лист источника", "default": u""}, ), }, u"градиент": { "title": u"Градиент", "hint": ( u"Маркер заголовка столбца (выбор из списка листа, накопление через запятую), " u"цвета min и max (пресеты или свой текст). " u"«Вся строка» — заливка всех столбцов диапазона. " u"«Сортировка» — перед градиентом по найденному столбцу-маркеру." ), "hint_lines": 4, "fields": ( { "id": "marker", "label": u"Маркер столбца", "type": "columns_pick", "default": u"сумм", }, { "id": "color_min", "label": u"Цвет min", "type": "combo", "choices": _header_plus_height_color_choices(), "default": u"зеленый", }, { "id": "color_max", "label": u"Цвет max", "type": "combo", "choices": _header_plus_height_color_choices(), "default": u"красный", }, { "id": "whole_row", "label": u"Вся строка", "type": "bool", "default": False, }, { "id": "sort", "label": u"Сортировка", "type": "bool", "default": False, }, { "id": "sort_dir", "label": u"Направление", "type": "combo", # UI как в диалоге «сортировка»: + / - "choices": (u"+", u"-"), "default": u"+", }, ), }, u"подсветка_по_порогу": { "title": u"Подсветка по порогу", "hint": ( u"Столбцы — выбор из списка (накопление через запятую; × — убрать последнее, ×× — очистить).\n" u"Маски * и ? в именах столбцов (например Сумма_*).\n" u"Пороги min/max в один ряд: подкраска при min ≤ значение ≤ max (пустая сторона — без границы).\n" u"«Применить для всей строки» — стиль всей строки по первому совпавшему столбцу.\n" u"Цвет заливки — пресет. Цвет шрифта — палитра; «Автоматический» — не менять цвет шрифта.\n" u"Жирный / курсив — в один ряд. Листы — как раньше (блоки / «на всех листах»).\n" u"Старый формат (маркер, один порог >): по-прежнему читается." ), "hint_lines": 5, "fields": ( { "id": "columns", "label": u"Столбцы", "type": "columns_pick", "default": u"", }, { "id": "threshold_min", "label": u"Порог min", "default": u"", "row_group": u"threshold", "row_group_slot": 0, }, { "id": "threshold_max", "label": u"Порог max", "default": u"", "row_group": u"threshold", "row_group_slot": 1, }, { "id": "color", "label": u"Цвет заливки", "type": "combo", "choices": _header_plus_height_color_choices(), "default": u"светло_красный", }, { "id": "font_color", "label": u"Цвет шрифта", "type": "combo", "choices": _header_plus_height_color_choices(), "default": u"", "with_auto_check": u"font_color_auto", }, { "id": "font_color_auto", "label": u"Автоматический цвет шрифта", "type": "bool", "default": True, "pair_after": u"font_color", }, { "id": "whole_row", "label": u"Применить для всей строки", "type": "bool", "default": False, }, { "id": "bold", "label": u"Жирный шрифт", "type": "bool", "default": False, "row_group": u"font_style", "row_group_slot": 0, }, { "id": "italic", "label": u"Курсив", "type": "bool", "default": False, "row_group": u"font_style", "row_group_slot": 1, }, ), }, u"условное_форматирование": { "alias_of": u"подсветка_по_порогу", }, u"подкрасить_пороги": { "alias_of": u"подсветка_по_порогу", "title": u"Подкрасить пороги", }, u"формат_даты": { "title": u"Формат даты", "hint": ( u"Формат: пусто — из глобальных настроек. Столбцы: буквы, номера или " u"имена заголовков через запятую; пусто — авто по типу ячеек " u"(при «Конвертировать текст в число» — ещё по 3 верхним строкам). " u"Маркеры — подстроки в заголовке (если столбцы не заданы)." ), "hint_lines": 4, "fields": ( { "id": "format", "label": u"Формат даты", "type": "combo", "choices": (), "default": u"", }, {"id": "columns", "label": u"Столбцы", "default": u""}, {"id": "markers", "label": u"Маркеры заголовка", "default": u""}, ), "convert_existing": True, "convert_label": u"Конвертировать текст в дату", }, u"формат_деньги": { "title": u"Формат денег / чисел", "hint": ( u"Формат: пусто — числовой формат из глобальных настроек. Столбцы: " u"буквы, номера или имена; пусто — автоопределение числовых столбцов " u"(при «Конвертировать текст в число» — ещё текстовые числа в 3 " u"верхних строках). Маркеры — подстроки в заголовке." ), "hint_lines": 4, "fields": ( { "id": "format", "label": u"Числовой формат", "type": "combo", "choices": (), "default": u"", }, {"id": "columns", "label": u"Столбцы", "default": u""}, {"id": "markers", "label": u"Маркеры заголовка", "default": u""}, ), "convert_existing": True, "convert_label": u"Конвертировать текст в число", }, u"удалить_столбцы": { "title": u"Удалить столбцы", "hint": ( u"Столбцы для удаления (через запятую): имена из списка, подстроки заголовка " u"(или шаблон *), индексы 1-based и буквы (A, C). Выбор из списка накапливается." ), "hint_lines": 3, "fields": ( { "id": "markers", "label": u"Столбцы / маркеры", "type": "columns_pick", "default": u"", }, ), }, u"сетка": { "title": u"Сетка", "hint": ( u"Толщина (тонкая/толстая/число) и цвет рамки. Пример: толстая/#666666. " u"«Включая заголовок» — сетка и на строке заголовков (по умолчанию выкл.)." ), "hint_lines": 3, "fields": ( {"id": "width", "label": u"Толщина", "default": u"тонкая"}, {"id": "color", "label": u"Цвет", "default": u""}, { "id": "include_header", "label": u"Включая заголовок", "type": "bool", "default": False, }, ), }, u"высота_строки": { "title": u"Высота строки", "hint": u"Строки: all или 2,3,4; высота в мм (0 = скрыть). Пустой лист — текущий лист шага.", "fields": ( {"id": "rows", "label": u"Строки (all / список)", "default": u"all"}, {"id": "height_mm", "label": u"Высота, мм", "default": u"5"}, ), }, u"отступ": { "title": u"Отступ", "hint": u"Выравнивание left/center/right, шаги, столбцы через запятую (пусто — все).", "fields": ( {"id": "h_align", "label": u"Выравнивание", "default": u"left"}, {"id": "steps", "label": u"Шаги", "default": u"1"}, {"id": "columns", "label": u"Столбцы", "default": u""}, ), }, u"шрифт": { "title": u"Шрифт", "hint": u"Имя; размер данных; размер заголовка. «—» или пусто — не менять.", "fields": ( {"id": "name", "label": u"Имя", "default": u""}, {"id": "size_data", "label": u"Размер данных", "default": u""}, {"id": "size_header", "label": u"Размер заголовка", "default": u""}, ), }, u"ширина_столбцов": { "title": u"Ширина столбцов", "hint": u"Столбцы: all или 1,2,3; ширина в мм (0 = скрыть).", "fields": ( {"id": "columns", "label": u"Столбцы (all / список)", "default": u"all"}, {"id": "width_mm", "label": u"Ширина, мм", "default": u"30"}, ), }, u"перенос": { "title": u"Перенос", "hint": u"Перенос текста в данных; опционально включая строку заголовков.", "fields": ( {"id": "wrap", "label": u"Перенос", "type": "bool", "default": True}, { "id": "include_header", "label": u"Включая заголовок", "type": "bool", "default": False, }, ), }, u"перенос_и_авто_высота": { "alias_of": u"перенос", "title": u"Перенос и авто-высота", "hint": u"Перенос + автоподбор высоты строк; «Включая заголовок» — и для заголовка.", }, u"заголовок_плюс_высота": { "title": u"Заголовок + высота", "hint": ( u"Высота заголовка в мм, выравнивание, шрифт и цвета. " u"Гориз.: left/center/right (л/ц/п); верт.: top/center/bottom (в/ц/н). " u"Цвета — имя (excel_header, серый…) или #hex. " u"«Автоматически» для цвета шрифта — контраст к заливке (по умолчанию)." ), "hint_lines": 5, "fields": ( {"id": "height_mm", "label": u"Высота, мм", "default": u"12.7"}, { "id": "h_align", "label": u"Гориз.", "type": "combo", "choices": _HEADER_PLUS_HEIGHT_HORI_CHOICES, "default": u"center", }, { "id": "v_align", "label": u"Верт.", "type": "combo", "choices": _HEADER_PLUS_HEIGHT_VERT_CHOICES, "default": u"center", }, {"id": "font_name", "label": u"Шрифт", "default": u""}, {"id": "font_size", "label": u"Размер, pt", "default": u""}, { "id": "fill_color", "label": u"Заливка", "type": "combo", "choices": _header_plus_height_color_choices(), "default": u"", }, { "id": "font_color", "label": u"Цвет шрифта", "type": "combo", "choices": _header_plus_height_color_choices(), "default": u"", }, { "id": "font_color_auto", "label": u"Автоматически (цвет шрифта)", "type": "bool", "default": True, }, { "id": "bold", "label": u"Жирный шрифт", "type": "bool", "default": False, }, ), }, u"зебра_диапазон": { "title": u"Зебра диапазон", "hint": u"Роли header/even/odd — заливка/шрифт (как в C: header:excel_header/белый).", "fields": ( {"id": "header", "label": u"Заголовок (заливка/шрифт)", "default": u""}, {"id": "even", "label": u"Чётные", "default": u""}, {"id": "odd", "label": u"Нечётные", "default": u""}, ), }, u"конкатенация_столбцов": { "title": u"Конкатенация столбцов", "hint": u"Имя нового столбца, разделитель (пусто = склейка), индексы 1-based через запятую.", "fields": ( {"id": "new_column", "label": u"Имя столбца", "default": u"Полный_Код"}, {"id": "separator", "label": u"Разделитель", "default": u"|"}, {"id": "columns", "label": u"Столбцы (1,3,5)", "default": u"1,3,5"}, ), }, u"применить_формулу": { "title": u"Применить формулу", "hint": ( u"Столбец результата и формула Calc. " u"{row_id} — строка данных (1-based), {col_id} — столбец вставки (A, B, …). " u"[Имя] / {Имя} — столбец по заголовку. " u"Формат — NumberFormat всего столбца (пусто — с первой строки / соседнего). " u"Лист в блоке — только для него; пусто — все листы шага." ), "hint_lines": 4, "fields": ( {"id": "column", "label": u"Столбец", "default": u"Итого"}, { "id": "formula", "label": u"Формула", "default": u"=IFERROR({col_id}{row_id-1}+1;1)", }, { "id": "format", "label": u"Формат столбца", "type": "combo", "choices": (), "default": u"", }, { "id": "as_values", "label": u"Как значение (после протяжки)", "type": "bool", "default": False, }, ), }, u"удаление_строк": { "title": u"Удаление строк", "hint": ( u"columns — пустые столбцы (1,A,ФИО); formula — условие удаления " u"({row_id}, {col}{row-1}, R[-1]C — как в «применить_формулу»)." ), "fields": ( { "id": "mode", "label": u"Режим", "type": "combo", "choices": (u"columns", u"formula"), "default": u"columns", }, {"id": "columns", "label": u"Столбцы", "default": u"1,A,ФИО"}, {"id": "formula", "label": u"Формула", "default": u""}, ), }, u"пропуск_пустых_строк": { "alias_of": u"удаление_строк", "title": u"Пропуск пустых строк", }, u"группировка_по_столбцу": { "title": u"Группировка по столбцу", "hint": u"Подстрока в заголовке столбца группировки.", "fields": ( {"id": "marker", "label": u"Маркер", "default": u"группа"}, ), }, u"стиль_печати": { "title": u"Стиль печати", "hint": u"landscape/portrait и число страниц по ширине (0 = не вписывать).", "fields": ( {"id": "orientation", "label": u"Ориентация", "default": u"landscape"}, {"id": "fit_pages", "label": u"Вписать в страниц", "default": u"1"}, ), }, u"заполнение_вниз": { "title": u"Заполнение вниз", "hint": u"Столбцы: номер, буква или имя заголовка через запятую.", "fields": ( {"id": "columns", "label": u"Столбцы", "default": u"ФИО,Отдел"}, ), }, u"копировать_значения": { "title": u"Копировать значения", "hint": u"Столбцы для копирования; «Весь лист» — без списка столбцов.", "fields": ( {"id": "whole_sheet", "label": u"Весь лист", "type": "bool", "default": False}, {"id": "columns", "label": u"Столбцы", "default": u"Сумма"}, ), }, u"замена_значений": { "title": u"Замена значений", "hint": ( u"Заменить подстроки в текстовых столбцах (выбор столбцов из списка листа).\n" u"find/replace через «;»: одно replace на все find или поштучно (N=N).\n" u"В find допускается * (любые символы слева/справа). Пустое replace → _ПУСТО_ (стирание).\n" u"Служебные replace: _ПУСТО_, _ПОВТОР*N_, _РЕГИСТР_ВВЕРХ_, _РЕГИСТР_ВНИЗ_." ), "hint_lines": 5, "fields": ( { "id": "columns", "label": u"Столбцы", "type": "columns_pick", "default": u"ФИО", }, {"id": "find", "label": u"Найти (через ;)", "default": u"ООО"}, {"id": "replace", "label": u"Заменить (1 или N)", "default": u"ОБЩЕСТВО"}, { "id": "case_insensitive", "label": u"Без учета регистра", "type": "bool", "default": True, }, { "id": "squeeze_spaces", "label": u"Сжать пробелы", "type": "bool", "default": True, }, ), }, u"текстовые_операции": { "title": u"Текстовые операции", "hint": ( u"Визуальный конструктор: стек ops, столбцы листа, нетекст/ошибка по-русски.\n" u"ops: trim, collapse_ws, case, lang_homoglyphs, reverse, base64, sha256, guid, encrypt/decrypt." ), "hint_lines": 3, "fields": ( { "id": "columns", "label": u"Столбцы", "type": "columns_pick", "choices_from_headers": True, "default": u"ФИО", }, { "id": "non_text", "label": u"Нетекст", "type": "combo", "choices": (u"пропуск", u"как текст", u"ошибка"), "default": u"пропуск", }, { "id": "on_error", "label": u"При ошибке op", "type": "combo", "choices": (u"оставить до ошибки", u"очистить ячейку", u"остановить"), "default": u"оставить до ошибки", }, ), }, u"переименовать_лист": { "title": u"Переименовать лист", "hint": u"Новое имя; лист слева — исходное имя (пусто = текущий лист шага).", "fields": ( {"id": "new_name", "label": u"Новое имя", "default": u"Итоговый"}, ), }, u"переименовать_столбцы": { "title": u"Переименовать столбцы", "hint": ( u"Старое имя — выбор из заголовков (накопление через запятую; " u"если в имени есть запятая — через «;»). × — убрать последнее, ×× — очистить.\n" u"Новое имя — вручную, те же разделители и порядок.\n" u"Пары сопоставляются по позиции: 1-е старое → 1-е новое и т.д." ), "hint_lines": 3, "fields": ( { "id": "old", "label": u"Старое наименование", "type": "columns_pick", "choices_from_headers": True, "default": u"Сумма", }, { "id": "new", "label": u"Новое наименование", "type": "columns_pick", "default": u"Итого_сумма", }, ), }, u"переставить_столбцы": { "title": u"Переставить столбцы", "hint": ( u"Лист слева обязателен (не «Все»). Столбцы — через запятую. " u"«Копировать» — оставить исходные и вставить копии; " u"«Новые имена» — заголовки копий (через запятую/;, пусто — авто _2). " u"Опорный столбец — единственный; при переносе если он в списке — исключается." ), "fields": ( {"id": "columns", "label": u"Столбцы", "default": u"C,Сумма"}, { "id": "position", "label": u"Куда", "type": "combo", "choices": ( u"_начало_", u"_конец_", u"_перед_", u"_после_", ), "default": u"_конец_", }, { "id": "relative_column", "label": u"Опорный столбец", "default": u"Итого", }, { "id": "copy", "label": u"Копировать (не перемещать)", "type": "bool", "default": False, }, { "id": "new_names", "label": u"Новые имена копий", "default": u"", }, ), }, u"количество_значений": { "title": u"Количество значений", "hint": ( u"Новый столбец — сколько строк в диапазоне с тем же ключом " u"(столбцы ключа через запятую). По умолчанию trim вкл., регистр не важен." ), "fields": ( {"id": "new_column", "label": u"Имя столбца", "default": u"Количество"}, {"id": "key_columns", "label": u"Столбцы ключа", "default": u"ФИО,Отдел"}, {"id": "trim", "label": u"Обрезать пробелы", "type": "bool", "default": True}, { "id": "case_sensitive", "label": u"Учитывать регистр", "type": "bool", "default": False, }, ), }, u"копировать_лист": { "title": u"Копировать лист", "hint": ( u"Полная копия вкладки (как на ярлычке листа). Лист слева — когда выполнять шаг.\n" u"ODS (xml_excel_ods): если задать columns + skip_empty, копируются только эти столбцы " u"и пропускаются пустые строки." ), "hint_lines": 3, "fields": ( {"id": "source_sheet", "label": u"Лист-источник", "default": u"Шаблон"}, {"id": "dest_sheet", "label": u"Имя копии", "default": u"Копия_Шаблон"}, {"id": "columns", "label": u"Столбцы (опц.)", "default": u""}, { "id": "skip_empty", "label": u"Пропускать пустые строки", "type": "bool", "default": False, }, { "id": "skip_empty_columns", "label": u"Колонки для пустоты (опц.)", "default": u"", }, {"id": "header_row", "label": u"Строка заголовков", "default": u"1"}, ), }, u"преобразовать_числа": { "title": u"Преобразовать числа", "hint": u"Столбцы (имена или индексы 1-based); пусто — все столбцы строки.", "fields": ( {"id": "columns", "label": u"Столбцы", "default": u"Сумма,Количество"}, ), }, u"цвет_текста_по_значению": { "title": u"Цвет текста по значению", "hint": u"Подстрока в заголовке столбца-источника (по умолчанию «статус»).", "fields": ( {"id": "marker", "label": u"Маркер столбца", "default": u"статус"}, ), }, } _INNER_CODEC_DIALOG_REGISTRY = { u"сортировка": { "title": u"Сортировка", "hint": u"Примеры: «Сводная | Сумма -> - , Дата -> + ; Orders | Сумма -> -» или без листа «Сумма -> -»", }, u"текстовые_операции": { "title": u"Текстовые операции", "hint": u"Стек ops + столбцы; нетекст/ошибки — по-русски в комбо.", }, u"нормализация_текста": { "title": u"Текстовые операции", "hint": u"Legacy-алиас «текстовые_операции».", "alias_of": u"текстовые_операции", }, u"раскрасить": { "title": u"Раскрасить блоки", "hint": u"Примеры: «Сводная | Отдел -> голубой%белый/+!граница ; Orders | A,B -> #E2EFDA/-»", "alias_of": u"раскрасить_блоки", }, u"раскрасить_блоки": { "title": u"Раскрасить блоки", "hint": u"Примеры: «Сводная | Отдел -> голубой%белый/+!граница»", }, } # Каталог ops / подписи для визуального конструктора текстовые_операции NORMALIZE_OP_CHOICES = ( (u"trim", u"Обрезать пробелы по краям"), (u"collapse_ws", u"Убрать лишние пробелы"), (u"case", u"Регистр"), (u"lang_homoglyphs", u"Омоглифы RU/EN"), (u"reverse", u"Перевернуть текст"), (u"base64_encode", u"Base64: кодировать"), (u"base64_decode", u"Base64: декодировать"), (u"sha256", u"SHA-256"), (u"guid", u"GUID в пустые ячейки"), (u"encrypt", u"Зашифровать"), (u"decrypt", u"Расшифровать"), ) NORMALIZE_OP_LABEL = {code: label for code, label in NORMALIZE_OP_CHOICES} NORMALIZE_OP_CODE = {label.casefold(): code for code, label in NORMALIZE_OP_CHOICES} NORMALIZE_CASE_MODES = ( (u"lower", u"нижний"), (u"upper", u"верхний"), (u"proper", u"как имена (Proper)"), (u"sentence", u"предложение"), (u"toggle", u"инверсия регистра"), ) NORMALIZE_CASE_LABEL = {code: label for code, label in NORMALIZE_CASE_MODES} NORMALIZE_CASE_CODE = {label.casefold(): code for code, label in NORMALIZE_CASE_MODES} NORMALIZE_NON_TEXT_CHOICES = ( (u"skip", u"пропуск"), (u"coerce", u"как текст"), (u"error", u"ошибка"), ) NORMALIZE_NON_TEXT_LABEL = {code: label for code, label in NORMALIZE_NON_TEXT_CHOICES} NORMALIZE_NON_TEXT_CODE = {label.casefold(): code for code, label in NORMALIZE_NON_TEXT_CHOICES} NORMALIZE_ON_ERROR_CHOICES = ( (u"keep", u"оставить до ошибки"), (u"empty", u"очистить ячейку"), (u"stop", u"остановить"), ) NORMALIZE_ON_ERROR_LABEL = {code: label for code, label in NORMALIZE_ON_ERROR_CHOICES} NORMALIZE_ON_ERROR_CODE = {label.casefold(): code for code, label in NORMALIZE_ON_ERROR_CHOICES} _VLOOKUP_CELL_HINTS = ( u"Левая таблица join: Лист|Начало_строки|Начало_столбца|Строка_заголовков.\n" u"Имя листа — как в источнике; при копировании подставится префикс N_.", u"Правая (справочная) таблица — тот же формат через |.", u"Общий ключ: Ключ_сравнения: A,B\n" u"Разные: Ключ_сравнения_левый: … # Ключ_сравнения_правый: …", u"Столбцы правой таблицы для подтягивания (через , или ;).", u"Подсветка: #FFF2CC, серый, заливка/шрифт (как у зебры); «Нет» — без подсветки.\n" u"Заполнять_дубли: Да/Нет (всегда в ячейке).\n" u"Мульти_совпадение_в_одну_ячейку: Да/Нет — все совпадения в одну ячейку через перенос строки.\n" u"Заполнитель_для_не_найдено: по умолчанию #Н/Д (#N/A, =NA()); _ПУСТО_ или _EMPTY_ — пустая ячейка.\n" u"Булево: +/-, 1/0, true/false, yes/no, истина/ложь (регистр не важен).", ) _VLOOKUP_COLOR_PRESETS = ( u"#FFFF00", u"#FFF2CC", u"excel_highlight", u"серый", u"голубой", u"голубой/синий", u"белый/черный", ) _VLOOKUP_COLOR_PRESET_EMPTY = u"— выберите пресет —" _VLOOKUP_NOT_FOUND_FROM_F_RE = re.compile( r"Заполнитель_для_не_найдено\s*:\s*([^;\r\n]+)", re.IGNORECASE | re.UNICODE, ) _PIVOT_DATA_FUNCTIONS = ( (u"SUM", u"Сумма"), (u"COUNT", u"Количество"), (u"AVERAGE", u"Среднее"), (u"MAX", u"Максимум"), (u"MIN", u"Минимум"), (u"PRODUCT", u"Произведение"), (u"STDDEV", u"Станд. отклонение"), (u"VAR", u"Дисперсия"), ) _PIVOT_FN_LABEL = {code: label for code, label in _PIVOT_DATA_FUNCTIONS} _PIVOT_FN_CODE = {label.casefold(): code for code, label in _PIVOT_DATA_FUNCTIONS} _PIVOT_REFRESH_BUSY = {} _WP_SCENARIOS = None