В этом уроке мы рассмотрим основы доступа к API Google Sheets через Python и использования его для превращения нашего листа в красивую пиксельную фотографию, установив цвет фона ячеек листа.

Если вы хотите прыгнуть вперед, заблудиться или просто очень нетерпеливы, вы можете проверить репозиторий Github здесь: https://github.com/woodserino/hacking-google-sheets

Предпосылки:

  • 1 х аккаунт Google Диска с доступом к Google Таблицам
  • 1 x Базовое понимание Python
  • Python › 2.6 и pip установлены

Обзор псевдокода:

1. Authenticate for Google Sheets API
2. Grab an image
3. Iterate through each row and column of the image and grab the RGB value of each pixel
4. Add each RGB value to an API request to set the background colour of cells in the sheet

Инструкции

Шаг 1

Перейдите на страницу Python Quickstart в Google и нажмите Включить API здесь https://developers.google.com/sheets/api/quickstart/python.

Шаг 2

Выберите «Настольное приложение» в модальном окне и нажмите «Создать».

Шаг 3

Создайте новую папку для своего проекта и загрузите файл конфигурации клиента (credentials.json) в эту папку, нажав большую синюю кнопку «Загрузить». (Скопируйте свой идентификатор клиента и секрет клиента в новый текстовый файл для безопасного хранения, если хотите — они нам не понадобятся для этого руководства).

Шаг 4

В соответствии с руководством по быстрому запуску Python установите клиентскую библиотеку Google с помощью команды

pip install — upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

Шаг 5

Вам также нужно будет выполнить следующее, чтобы установить библиотеку PIL.

pip install Pillow

Шаг 6

Вместо загрузки файла quickstart.py поставщика из руководства по быстрому запуску Python загрузите следующий код в новый файл с именем sheets1.py в том же каталоге, что и ваш файл учетных данных.json.

from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from PIL import Image
#
# Edit Here: The ID of your spreadsheet.
#
SHEET_ID = '{sheetId}'
IMAGE_FILENAME = 'test.png'
def main():
    #
    # Replace me for Step 8
    #
    # Replace me for Step 9
    #
    # Replace me for Step 12
    #
if __name__ == '__main__':
    main()

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

Шаг 7

Пока мы здесь, создайте новый файл Google Sheets, используя ту же учетную запись, с которой вы аутентифицировались ранее. URL-адрес нового листа должен выглядеть примерно так:

https://docs.google.com/spreadsheets/d/1_-4iZ_3rEoTHUTwkxG2AFHSJbyUsUiyt8yKzov-4q14f/edit#gid=0

Строка после /d/ и перед /edit (в данном случае 1_-4iZ_3rEoTHUTwkxG2AFHSJbyUsUiyt8yKzov-4q14f) — это идентификатор вашего листа. Замените {sheetId} в sheets1.py этим идентификатором.

Вам также нужно будет отформатировать размер ячейки листа, чтобы разместить увеличенное изображение. Выберите все ячейки на вашем листе (CMD + A на Mac, CTRL + A на Windows), а затем перетащите ширину столбца, чтобы она была крошечной, как на этом снимке экрана. Чем меньше вы сделаете ячейки, тем выше будет «разрешение» изображения.

Вам также нужно будет добавить больше столбцов. Когда все выбрано, щелкните правой кнопкой мыши и выберите «Вставить 26 столбцов». Затем выберите все и повторите все снова, на этот раз выберите «Вставить 52 столбца». Это оставит вас со 104 столбцами.

Шаг 8

Скопируйте/вставьте следующий код в Sheets1.py над строкой, где написано «Замените меня на шаге 8».

#
# Set up credentials and save in token.pickle
#
SCOPES = ['https://www.googleapis.com/auth/spreadsheets']
creds = None
if os.path.exists('token.pickle'):
    with open('token.pickle', 'rb') as token:
        creds = pickle.load(token)
if not creds or not creds.valid:
    if creds and creds.expired and creds.refresh_token:
        creds.refresh(Request())
    else:
        flow = InstalledAppFlow.from_client_secrets_file(
            'credentials.json', SCOPES)
        creds = flow.run_local_server(port=0)
    with open('token.pickle', 'wb') as token:
        pickle.dump(creds, token)

Сохраните свой код. Затем в Терминале перейдите в каталог вашего проекта и запустите python sheets1.py. Ваш интернет-браузер по умолчанию должен открыться с экраном входа в Chrome — он появится только при первом запуске кода.

Выполните процесс входа в систему [ПРИМЕЧАНИЕ. Убедитесь, что вы входите в учетную запись с помощью Google Таблицы из шага 1], пока не увидите экран с надписью The authentication flow has completed. You may close this window. Теперь вы должны увидеть токен. .pickle в каталоге вашего проекта. Если вы снова запустите python sheet1.py, ничего не должно произойти — это означает, что вы успешно аутентифицировали свой скрипт для доступа к своей учетной записи Google.

Шаг 9

Скопируйте и вставьте следующий код в Sheets1.py поверх строки с надписью «Замените меня на шаге 9».

#
# Grab pixels from image
#
service = build('sheets', 'v4', credentials=creds)
sheetId = 0
im = Image.open(IMAGE_FILENAME)
rgb_im = im.convert('RGB')
rows, cols = im.size
requests = []
for x in range(0,rows):
    for y in range(0,cols):
        r, g, b = rgb_im.getpixel((x, y))
        print(r,g,b)
        #
        # Replace me for Step 10
        #

Вам также потребуется загрузить следующее изображение в каталог вашего проекта, сохраненное как test.png.

Снова запустите python sheets1.py, и вы должны увидеть набор чисел в вашем терминале (см. скриншот ниже). Этот новый код перебирает строки и столбцы test.png и печатает значения RGB для каждого пикселя. Это данные, которые мы собираемся использовать для установки цвета фона каждой ячейки на листе в соответствии с изображением.

Шаг 10

Скопируйте и вставьте следующий код, чтобы заменить строку с надписью «Замените меня на шаге 10». Убедитесь, что вы соответствуете отступу (см. скриншот ниже).

#
# Add each pixel colour to the request
#
requests.append(
    {
      "repeatCell": {
        "range": {
          "sheetId": sheetId,
          "startRowIndex": x,
          "endRowIndex": x+1,
          "startColumnIndex": y,
          "endColumnIndex": y+1
        },
        "cell": {
          "userEnteredFormat": {
            "backgroundColor": {
              "red": (float(r)/255),
              "green": (float(g)/255),
              "blue": (float(b)/255)
            }
          }
        },
        "fields": "userEnteredFormat(backgroundColor)"
      }
    })

Этот код добавляет в конец списка requests словарь, содержащий форматирование, которое мы хотим применить к каждой ячейке.

Шаг 11

Скопируйте и вставьте следующий код, чтобы заменить строку с надписью «Замените меня на шаге 11».

#
# Send the request via the Google API
#
body = {
    'requests': requests
}
if len(requests) > 0:
    response = service.spreadsheets().batchUpdate(spreadsheetId=SHEET_ID,body=body).execute()

Это упаковывает список запросов и отправляет его в электронную таблицу через вызов batchUpdate в API листов.

Теперь мы можем запустить скрипт, снова набрав python sheets1.py в Терминале, и вы должны получить что-то вроде этого:

Мне пришлось поиграть с размером ячейки (так же, как в шаге 7) и уменьшить масштаб, чтобы получить правильное разрешение.

Если по какой-либо причине это не работает, сначала попробуйте проверить репозиторий Github здесь и загрузить sheets1_complete.py, чтобы убедиться, что вы не пропустили код.

Бонусный раунд

Если вы хотите сделать это странно, вы можете переключать значения R, G и B в запросах следующим образом:

"cell": {
  "userEnteredFormat": {
    "backgroundColor": {
      "red": (float(g)/255),
      "green": (float(b)/255),
      "blue": (float(r)/255)
    }
  }
},

Или поэкспериментируйте с rows и cols, или с чем-то еще. Сходить с ума.

Если вы хотите нарисовать свою фотографию:

  1. Замените файл test.png своим собственным или измените IMAGE_FILENAME = ‘test.png’, чтобы он указывал на ваше имя файла.
  2. Убедитесь, что на вашем листе достаточно столбцов и строк, чтобы обработать размер запроса.

Следующий