Всё началось с задачи создания отчёта по взаиморасчётам с клиентами и поставщиками. Маячила перспектива собирать все данные руками. Целый отдел из 7 девочек не знал, как подступиться к этому, учитывая, что база состояла более чем из 180 тыс. строк и велась в MS Access.
О чём речь
В одном крупном рекламном агентстве есть «зоопарк». В смысле «зоопарк» различных информационных систем, которые создавались годами силами самих сотрудников, пытавшихся хоть как-то автоматизировать ручную работу. В этой статье речь пойдёт об автоматизации работы отдела контроля медиазакупок (сокращённо «КЗ»). Это такое подразделение, контролирующее какой площадке сколько денег заплачено и нет ли переплат/недоплат. Важные люди для бизнеса, проще говоря. Так сложилось, что в этом отделе с 2010 года ведётся своя база этих самых транзакций, закрывающих документов, контрактов. Базу создавал продвинутый менеджер, поэтому она изначально создавалась на Access 2007, с кучей макросов, но без форм. Хранение данных разумеется в самом файле базы.
Всё началось с задачи, которую бухгалтерия поставила КЗ: выгрузить сведения по всем закрывающим документам в рамках определённого периода. Грубо говоря, нужна была табличка из 20 колонок в числе которых были номер и дата контракта с поставщиком, статус оплат по проекту, наличие актов и тому подобное. Заурядный отчёт, который мог превратить в ад жизнь 7 сотрудниц отдела КЗ. А всё дело в том, что при попытке выгрузить нужную информацию база безнадёжно висла. Таблички Access были не рассчитаны на вывод десятков тысяч записей. Движок не предполагал запросы с десятком LEFT JOIN. Индексы не помогали. Руководитель отдела каждый день приходила на работу, открывала базу и не могла даже подступиться к ручному сведению таблички из пары десятков тысяч строк. Бухгалтерия, между тем, поставила достаточно жёсткий дедлайн и ждала данных. Сотрудницы, бросив детей и мужей, готовились ночевать в офисе.
Lean
После такого безрадостного введения, давайте поговорим немного о теории и управлении. Итак, рекламное агентство продаёт сервис. Не рекламу. Реклама — это лишь предмет для разговора, то что мы умеем делать хорошо. Но платят нам за то, что мы быстро и в рамках комиссии сделаем за клиента всю грязную работу и даже лучше, чем он ожидает. Клиент ждёт от нас также рациональных предложений по улучшениям своих кампаний, по оптимальным способам достижения своих показателей. Тех показателей, которыми он сам отчитывается своему руководству. Само собой разумеется, что клиент ожидает идеальный документооборот, безупречные закрытия и феноменальную точность в соблюдении дедлайнов по ним. Возвращаясь к нашим девочкам, я до сих пор не понимаю, как они при помощи обычной базы на обычном аксессе всё это обеспечивали. Но суть не в этом. Короче говоря, для качественного сервиса нужно время. И здесь мы немного коснёмся концепции бережливого производства, поскольку оно на практике имеет прямое отношение к разбираемой здесь задаче.
Бережливое производство (по-английски «lean»), если говорить простыми словами, это такой способ производства продукта, при котором доля потерь стремится к нулю. Эта концепция является творческой переработкой опыта компании Toyota. Основная идея, в выявлении потерь по типичным направлениям вроде бракованной продукции, неоправданных задержках на складах, избыточной обработки, простоях, усушке/утруске и так далее. По данным некоторых источников, экономия от внедрения концепции lean на крупных предприятиях, исчисляется миллиардами рублей. Вы меня спросите, какое это имеет отношение к сервисной компании, такой как рекламное агентство? Самое прямое.
Мы продаём сервис. Для качественного сервиса нужно время. Время и люди – вот наш ресурс. А если люди сутками сидят и копипастят в эксельках, то это потери. Потери времени и, со временем, – людей. Неэффективность производства сервиса, если хотите. Исчисляется методом умножения почасовой ставки оклада на число излишне потраченных часов. Допустим сотрудник отдела контроля закупок получает условных 40 тысяч рублей в месяц за 160 часов работы. Или 250 рублей в час. Она вместо того, чтобы нажать на одну кнопочку и получить требуемый отчёт за 1 минуту, копипастит в течение пары недель. Причём не одна сотрудница, а весь отдел: 250 (ставка) x 8 (часов в день) x 10 (рабочих дней) x 7 (девочек). Получаем 140 тысяч рублей, потраченных на копипаст. Потери для качественного сервиса вообще трудно посчитать, потому, что, когда собирается отчёт методом копипаста, остальная работа либо стоит, либо делается непонятно как.
Половинчатое решение, ускоряющее ручную работу
Давайте перейдём от теории к практике. Итак, есть не выполнимая стандартными средствами задача: выгрузить отчёт. Кроме того, в перспективе есть необходимость как-то поставить процесс создания отчёта на поток, причём желательно силами самого отдела контроля закупок. Ниже описание решения, однако, не хотелось бы, чтобы оно было воспринято как готовый рецепт из «Тостера», но скорее, как концепция для работы со всеми подобными задачами. Даже более. В идеале, надо бы проанализировать все процессы компании и выявить этапы, которые можно автоматизировать по образцу, предлагаемому ниже.
Для решения указанных выше двух задач нам потребовались: MS SQL Server 2012 Express, AutoIt, PowerQuery.
Поскольку Access не позволяет делать сложные запросы из таблиц, содержащих сотни тысяч строк, было принято решение воспользоваться тяжёлой артиллерией, а именно MS SQL Server 2012 Express. Установка базы описана достаточно подробно вендором, поэтому не буду на этом останавливаться. Из Access экспортировали вручную соответствующие таблицы (в которых данные для отчёта) через предварительно созданное соединение ODBC:
Далее повесили индексы на все экспортированные нами таблицы, что позволило увеличить скорость отработки запроса в 4-6 раз:
Далее написали многострочный запрос с кучей LEFT JOIN, GROUP BY и WHERE. Детали его здесь приводить не буду, но они и не значимы. Важен принцип. После отработки запроса делаем Ctrl+a (выделить все результаты). Далее идём в предварительно подготовленную эксельку и вставляем туда данные Ctrl+v. Приводим в порядок форматы, сохраняем, отправляем в бухгалтерию Процесс занял не две недели, а 10 минут. Но одни проблема: выполнить его под силу только очень хорошо прокаченному специалисту. И любые проблемы (например, ошибка экспорта таблицы из-за даты в неправильном формате) превращаются в те ещё танцы с бубном (любые ошибки формата решаются через экспорт в Excel и импорт его уже в MS SQL). Одним словом, эти костыли было необходимо автоматизировать.
Правильное решение с помощью AutoIt
И тут на сцену выходит всесильный AutoIt. Это крайне потенциальная вещь, если в компании работают хотя бы десятки сотрудников. Есть ряд действий, которые выполняет определённый процент людей: открыть таймшиты вовремя, запустить среду разработки/отладки (IDE+базу+окно с git+бэкап сделать), открыть систему учёта по нужному списку проектов и тому подобные мелочи, которые вроде бы незначительные, но отъедают десятки минут рабочего времени сотен людей. В сумме это получается гигантская напрасная работа, которую вполне можно поручить программному роботу. Но вернёмся к нашей задаче.
Итак, необходимо автоматизировать описанный выше процесс, причём действий должно быть всего два: запуск процесса, получение готового отчёта. Можно было бы написать некую прогу, которая подключается сначала к Access, выгружает из него данные, затем заливает их в MS SQL и запускает нужный запрос, результаты которого потом выгружает в результирующий Excel. На это ушли бы недели разработки, ловли ошибок. Было решено воспользоваться готовой инфраструктурой приложений, которой будет управлять скрипт на AutoIt. Выгрузку готового отчёта поручили PowerQuery, поскольку он заточен под такие задачи.
Для того, чтобы всё отработало, необходимо было заранее сделать в исходном файле Access макрос, который экспортирует данные в MS SQL:
Public Function TransferKz()
'Макрос экспортирует таблицы в локальную базу MSSQL
'Для выгрузки отчёта
Dim Tables(1 To 11) As String
Dim i As Integer
Tables(1) = "table1"
Tables(2) = " table2"
Tables(3) = " table3"
'…
For i = 1 To 11
DoCmd.TransferDatabase acExport, "ODBC Database", "ODBC;DSN=kz;", acTable, Tables(i), Tables(i)
Next i
MsgBox "Tables exported"
End Function
Кроме того, заранее подготовлен файл Excel, который содержит модель PowerQuery, выгружающую необходимые данные из базы. Здесь данная модель рассматриваться не будет. Но ознакомиться с принципами работы PowerQuery можно здесь и здесь.
При запуске скрипта AutoIt происходит следующее:
- Высвечивается окошко с предупреждением о том, что во время работы скрипта нельзя трогать клавиатуру и мышку:
MsgBox(0, «Мы начинаем», «Во время работы скрипта нельзя нажимать никакие кнопки и открывать окна. Лучше просто отойти от компьютера на 1-2 минуты».
- Копируется файл MS Access, содержащий нужные нам данные:
FileCopy($file_path_from, $file_path_to, $FC_OVERWRITE + $FC_CREATEPATH)
- Запускается MS SQL Management Studio:
Run($ssms_path) WinWaitActive("Соединение с сервером") Send($sql_server_address & "{ENTER}") WinWaitActive("Microsoft SQL Server Management Studio")
- Удаляются все таблицы в базе КЗ. $small_sleep – переменная содержащая время паузы перед командами. Необходимо т.к. в противном случае приложения иногда не успевают окончательно отработать команду перед запуском следующей:
Send("^{o}") Sleep($small_sleep) Send($sql_dir & $sql_file_Query_drop_tables) Sleep($small_sleep) Send("{ENTER}") Sleep($small_sleep) Send("{F5}") Sleep($small_sleep) ;Закрытие окна без сохранения Send("^{F4}{TAB}{ENTER}")
- Запускается файл Access полученный в ходе шага №2:
;Запускаем базу Access и сразу же макрос для экспорта таблиц Run( $db_path & " /x TransferKz" ) ;Ждём окно: «Tables exported» WinWaitActive("[CLASS:#32770]") ;Закрываем окно Access Send("!+{F4}",0)
- Создаём индексы на только что экспортированные таблицы:
;Открываем окно с скриптом, который предстоит запускать WinActivate("Solution1 - Microsoft SQL Server Management Studio") Send("^{o}") Sleep($small_sleep) Send($sql_file_indexes) Sleep($small_sleep) Send("{ENTER}") Sleep($small_sleep) Send("{F5}") Sleep($small_sleep) ;Закрываем окно MSSQL Management Studio Send("!+{F4}",0)
- Запускается Excel содержащий необходимую нам модель выгрузки данных из MS SQl:
ShellExecute($file_ excel)
Работа скрипта AutoIt закончена. Теперь необходимо просто нажать на кнопку «Обновить» в открытом файле Excel и дождаться получения требуемого отчёта. Время отработки скрипта от щелчка мышкой до выгрузки отчёта – 3,5 минуты из которых 2 это паузы между шагами.
Выводы
Как вскользь упомянуто выше, мы прорабатывали вопрос решения проблемы следующими способами: радикально переписав базу отдела контроля закупок практически с нуля, либо переместив таблицы в MS SQL и продолжив использовать MS Access в качестве «фронтэнда». Основное препятствие для реализации этих планов – время. Да, можно сделать базу на 1С, потратив на это два-три месяца, деньги на разработчика. 1С не подходит для целостного решения учёта и документооборота в нашем агентстве. Была выбрана другая система, поэтому так или иначе нам придётся в скором времени переделываться всё с нуля уже на новой платформе. Реализация указанного выше набора методов заняла 3 дня. 2 из которых были потрачены на тестирование уже работающей системы и отладку запроса в MS SQL. Ни один профессиональный разработчик не приложил руку к указанному выше коду. Всё делалось своими силами, в свободное от остальных проектов время. Компания осталась при своих деньгах. Время сохранено на нечто более полезное, чем копипаст. Бережливое производство в действии.
Комментарии (12)
webzlo
25.11.2016 02:59Вот интересно, если положить эту базу на Windows Server 2008R2 должно существенно быстрее работать и в самом Access'е. Просто сталкивался с такой проблемой: на Win7 лежала база и при достижении размера в 2Гб приложение которое с ней работало просто висло намертво. После того как базу и приложение положил на сервер такой проблемы больше не возникало. Хотя периодически базу все же чищу на всякий случай. Видимо дело в разных версиях драйверов ODBC
krokodilo
25.11.2016 11:35у Аксесса же 2ГБ официально максимальный размер базы данных, понятно что приложение висло
FatLamer
25.11.2016 11:35+12 гига для голого Аксесса — это жесть. На типовую связку MS SQL и Аксесс, в качестве морды к нему, переходят при гораздо меньших обьемах базы.
А при корпоративном использовании, как у автора статьи, такую связку необходимо использовать изначально. Тогда и данные туда-сюда гонять не придется, плюс Аксесс прекрасно делает отчеты под Эксель.nsuvorov
25.11.2016 11:37Мы вот были в раздумьях: делать как вы написали или уже на новую платформу их пересаживать сразу, а пока пусть вышеописанный костыль юзают. Выбрали второй вариант. На первый дофига времени, а пересаживать всё равно придётся.
miss_dead
25.11.2016 11:35Избыточное изобилие информационных систем и отсутствие одного приемлемого решения — известная проблема. И если вы смогли ее решить для себя — молодцы! Представляю чего вам это стоило!
kh0
25.11.2016 22:48Моя success-story:
Работал я как-то полусисадмином в администрации городского поселения. Среди прочих, было там рабочее место паспортиста. С Парусом. Запросил район, какой-то хитрый отчет, которого в Парусе не было. Причем срочно. Теоретически, отчеты под Парус писать можно, но сложно. В Парусе было подходящее отображение таблицей, но не все записи требовались, а только по некоторому условию. Из таблицы отображения данные копировались в буфер только по одному полю, без альтернатив. Был написан autoit-скрипт, который кликая по каждому полю каждой строки, писал данные в текстовый файл. За ночь он успел сделать два раза всю работу. Оба результата были сравнены на совпадение для страховки от глюков (Виста расслабляться не давала). Потом регуляркой были вычищены ненужные строки. То что осталось, я загузил в Excel. Что с этим делали дальше я не знаю. Чистого времени было потрачено где-то час, правда я неплохо владел Autoit и до этого. Как выкручивались другие администрации района я не знаю, наверное, липу сунули. Ура Autoit!mapatka
29.11.2016 22:58Не знаю, возможно уже у нас допилили, но сейчас можно «то что показывает» то и выгрузить.
Shadow_ru
25.11.2016 22:48>ушли бы недели разработки
Мнэээ, многовато для банального перекладывателя данных.
Ну и бонус — при запросе не через Access, а через ODBC Jet в любом ЯВУ ваши запросы скорее всего отработали бы нормально.nsuvorov
25.11.2016 23:00Вы знаете, у нас большой опыт работы с аутсорсинговой разработкой. Неделя ушла бы на объяснение задачи, вторая — на уточнение задачи по факту написанного (нерабочего) кода, пару недель — на доводку. И это если бы попался хороший разработчик, который не предложил бы с порога переписать всю базу «под себя». Плавали знаем. Внутренний разработчик справился бы быстрее. Но это не наш бизнес.
Shadow_ru
29.11.2016 19:22Я о том, что тот-же самый запрос который вешал Access — через ODBC вполне отработает, потом сдампить результат в какой-то файл. Есть такой фокус
VladC
Извините, просто любопытствую — чем не подошла 1С? Там достаточно удобно конструировать учетные системы, в т.ч. «с нуля», импорт/экспорт тоже не проблема, очень удобная система построения отчетов. Полагаю дело в стоимости платформы и лицензий?
sergarcada
1С — это не только затраты на покупку, это затраты времени, в первую очередь на обучение сотрудников. AutoIt3 — это костыль. Но этот костыль помогает продержаться на ногах до тех пор, пока не будет найдено лучшее решение. Помнится, работая в одном банке при пришлось на autoit3 писать утилитку для печати кредитных договоров. Стандартная банковская программа не умела это делать сама! Все ОСБ пользовалось ей около года, а потом уже и разработчики подтянулись. Так что AutoIt3 — это хороший инструмент для быстрой автоматизации.