В северном полушарии нынче зима, а это значит что пора на лыжи! Мы с друзьями поддались этому течению и приступили к подготовке нашего совместного зимнего отдыха. Детали всего процесса планирования раскрывать не буду, скажу лишь только, что мне выпала отв��тственная роль сбора магазинных чеков наших совместных трат.

Так как песочницей для наших планов выступили Google Docs, а конкретнее Таблицы, то мне захотелось разместить фото всех чеков на отдельном листе. Первая попытка вставить картинку в таблицу через привычный пункт меню «Вставка → Изображение» привела к тому что чек оказался поверх ячеек таблицы и моим друзьям IT-шникам такое оформление точно бы не приглянулось:



«Должен же быть способ вставить картинку в ячейку...», — подумал я. Google нашел этот способ с первого запроса: функция IMAGE(URL), как значение ячейки. Ну что ж, дело сделано:



Можно дальше идти смотреть лыжные уроки. Хотя…

...Google моментально среагировал на мой запрос «Online FineReader API» и выдал несколько статей с хабра о ABBYY Cloud OCR SDK. Быстрый просмотр доступных методов платформы подтвердил мои надежды и желанный ocrsdk.com/documentation/apireference/processReceipt был найден. Для осуществления задуманного недоставало понимания как вставить в ячейку таблицы пользовательскую функцию, которая будет вызывать методы обработки чека. Но и тут поиск меня не подвел и был найден Редактор скриптов Google.

Теперь дело за малым. Первым делом необходимо создать приложение ocrsdk. Делается это в процессе регистрации нового пользователя, так что с этим проблем не возникло. Письмо с паролем приложения, который необходим для аутентификации запросов, было отправлено сразу после завершения регистрации.

Далее в нашей Таблице выбираем пункт меню «Инструменты → Редактор скриптов» и создаем функцию processReceipt(imageUrl):

function processReceipt(imageUrl) {
    
    // Загружаем картинку чека
    var image =      UrlFetchApp.fetch(imageUrl);
  
    // Формируем заголовок авторизации, который состоит из имени приложения и пароля
    var pass = "GoogleDriveTest" + ":" + "********************"
    
    // Формируем POST запрос на обработку чека
    var url = "http://cloud.ocrsdk.com/processReceipt";
    var headers = {
        "Content-Type":"image/png",
        "Authorization" : "Basic " + Utilities.base64Encode(pass)
    };
    
    var options = {
        "method":"POST",
        "headers": headers,
        "payload" : image.getContent()
    };
    var response = UrlFetchApp.fetch(url, options);
    
  
    // Парсим XML ответа и находим в нем ID задачи по обработке нашего чека (больше деталей тут http://ocrsdk.com/documentation/apireference/processReceipt/)
    var document = XmlService.parse(response.getContentText())
    var id = document.getRootElement().getChildren()[0].getAttribute('id').getValue()
    
    var resultUrl
    
    // Ждем успешного завершения задачи и получаем url по которому можно получить результат обработки чека
    do {
        Utilities.sleep(3000)
        
        url = "http://cloud.ocrsdk.com/getTaskStatus" + "?taskId=" + id;
        headers = {
            "Authorization" : "Basic " + Utilities.base64Encode(pass)
        };
        
        options = {
            "method":"GET",
            "headers": headers,
        };
        
        response = UrlFetchApp.fetch(url, options);
        
        document = XmlService.parse(response.getContentText());
        if (document.getRootElement().getChildren()[0].getAttribute('status').getValue() == 'Completed') {
            resultUrl = document.getRootElement().getChildren()[0].getAttribute('resultUrl').getValue()
            break
        }
    } while(true)
        
    // Получаем результат обработки чека
    options = {
        "method":"GET",
    };
    
    response = UrlFetchApp.fetch(resultUrl, options);
    document = XmlService.parse(response.getContentText());
    
    // document содаржит XML нашего чека. Из-за моральных принципов реализацию функции findTotalPriceInReceiptXML я скрыл :)
    result = findTotalPriceInReceiptXML(document)
    
    return result
}

Всё сохраняем и идем обратно в таблицу. Чтоб сие чудо заработало, пришлось вынести в отдельную ячейку таблицы URL картинки чека. Наша функция теперь доступна как =processReceipt(ячейка с URL).



Всем хорошей зимней погоды и удачи на лыжных склонах!