В очень многих технических проектах используются данные, хранящиеся в таблицах; это может быть что угодно — описания сущностей, словари, локализации. Такие документы, обычно, предполагают доступ и редактирования не-программистами, и для этого, обыкновенно, используются таблицы (spreadsheets) Google Docs, которые после правок экспортируются в проект в виде CSV-файлов и далее подхватываются программно. Когда таких документов в проекте становится больше, чем один, начинаешь невольно задумываться об автоматизации экспорта.

API Google Sheets

Таблицы Google имеют, как выясняется, довольно богатый и удобный для быстрого подхватывания API, в том числе в виде простых GET-запросов на шаблонные адреса. Возможно скачать любой документ в уже приведённом к нужному формату виде по ссылке такого формата:

http://docs.google.com/feeds/download/spreadsheets/Export?key=<id-таблицы>&exportFormat=<формат>&gid=<id-листа>

где:

  • <id-таблицы> — идентификатор документа Google (вроде 12VNGN3xYpO_HBLCfrQc7RwBYA8kcm-B6PXFvt577Op0);
  • <формат> — формат экспорта: csv, tsv, pdf и т.д.;
  • <id-листа> — идентификатор листа в таблице, для которого будет выполнен экспорт; для первого листа это всегда 0.

Получить эти параметры из URL документа, с которым вы работаете, очень просто.

google-sheets-url

Если документ доступен любому по ссылке — никакой авторизации при этом не требуется.

Скрипт

Исходя из всей этой информации был написан следующий скрипт на PowerShell, экспортирующий документы по спецификации (массив $files в самом начале скрипта). Особенностью является то, что в случае, если для таблицы указано несколько идентификаторов листов, скрипт скачивает их все, а затем склеивает в один файл, что бывает необычайно полезно.


$files = @(
    @{id = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; format = "csv"; localPath = "Some\File.csv"; gid = 1391150485},
    @{id = "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY"; format = "tsv"; localPath = "Some\OtherFile.tsv"},
    @{id = "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"; format = "csv"; localPath = "AssembledFile.csv"; gid = @(0, 1053706290, 1554759468, 1031448317, 409153032, 983615731)}
    )
$downloadUri = "docs.google.com/feeds/download/spreadsheets/Export?key={0}&exportFormat={1}&gid={2}"
$progressPreference = "silentlyContinue" # For Invoke-WebRequest not to spawn GUI.

foreach ($file in $files) {
    if (-not $file.ContainsKey("format")) {
        $file.format = "csv"
    }

    if (-not $file.ContainsKey("gid")) {
        $gid = 0
    }
    else {
        $gid = $file.gid
    }

    if ($gid -isnot [System.Array]) {
        Write-Host ("Downloading document ``{0}``..." -f $file.localPath) -ForegroundColor Magenta -NoNewline
        Invoke-WebRequest ($downloadUri -f ($file.id, $file.format, $gid)) -OutFile $file.localPath
        Write-Host "done" -ForegroundColor Green
    }
    else {
        Write-Host ("Processing sheets for document ``{0}``..." -f $file.localPath) -ForegroundColor Magenta

        $guid = [guid]::NewGuid()
        $tempFolder = (Join-Path $env:TEMP $guid)
        New-Item -ItemType Directory -Path $tempFolder | Out-Null

        foreach ($sheet in $gid) {
            Write-Host ("`tDownloading sheet with GID ``{0}``..." -f $sheet) -ForegroundColor Magenta -NoNewline
            Invoke-WebRequest ($downloadUri -f ($file.id, $file.format, $sheet)) -OutFile (Join-Path $tempFolder $sheet)
            Write-Host "done" -ForegroundColor Green
        }

        Write-Host ("Assembling document ``{0}``..." -f $file.localPath) -ForegroundColor Magenta -NoNewline

        Get-Content (Join-Path $tempFolder $gid[0]) | Set-Content $file.localPath
        foreach ($sheet in ($gid | Select -Skip 1)) {
            (Get-Content (Join-Path $tempFolder $sheet) | Select -Skip 1) | Add-Content $file.localPath
        }

        Remove-Item $tempFolder -Recurse -Force | Out-Null
        Write-Host "done" -ForegroundColor Green
    }
}

Write-Host "Exporting complete." -ForegroundColor Blue

csv-export-example

comments powered by HyperComments