Introdução ao Planilhas Google em Python. Do registro à leitura de dados

Por um bom tempo, consegui enviar dados para o Excel, mas o mod está mudando, os usuários querem isso nas nuvens.

Tendo começado a traduzir vários projetos em Python, decidi que era hora de mudar (ou adicionar) ao Excel com algo mais moderno.

Quando encontrei a necessidade de trabalhar com planilhas do Google a partir do Python, fiquei com a ilusão de que tudo isso pode ser feito em alguns cliques. A realidade acabou sendo menos otimista, mas não temos outro globo.

Os artigos me ajudaram bastante:


Como sempre - quando você toma uma decisão pela primeira vez, é confrontado com uma série de perguntas que mais tarde causam apenas confusão - como alguém pode pensar sobre isso. Elementar!

Talvez eu tenha percorrido um longo caminho - ficarei feliz se você me corrigir.

Todas as ações foram executadas em um computador executando o Windows + Python 3.6.6 e também foi usado um notebook Jupyter.

As principais dificuldades que tive na fase de configurações preliminares. Encontrar um código viável não é difícil.

O código usado no artigo está disponível no repositório.

Inscreva-se nos serviços do Google e instale bibliotecas


Para trabalhar com tabelas, você precisa se registrar no Google, configurar o projeto e instalar as bibliotecas necessárias.

A documentação oficial em inglês está aqui .

Primeiro você precisa se registrar no gmail.com (você pode fazer isso sozinho). Então você precisa criar um projeto (como o Google fornece acesso aos seus serviços).

Esse é um processo longo e tedioso que permite que você entenda por que as interfaces do Google não são as mais convenientes e intuitivas (algumas pessoas pensam que a rede social do Google+ não decolou por esse motivo).

Para fazer isso, acesse console.developers.google.com/cloud-resource-manager e clique em "Criar projeto"



Digite o nome do projeto e clique em "Criar"



Na lista atualizada de projetos, vá ao menu "Permissões"


Na janela que se abre, clique em "Adicionar", digite seu endereço de e-mail no domínio gmail.com e selecione o grupo "Projeto" - "Proprietário"



Salve as alterações.

Pode parecer estranho que você tenha criado um projeto, mas é obrigado a emitir direitos para si mesmo. E isso é realmente estranho, mas era um caminho que precisava ser seguido no momento da elaboração deste curso, para que tudo começasse a funcionar como deveria.

Visite console.developers.google.com/cloud-resource-manager novamente

Selecione o menu Configurações no seu projeto



Na janela que se abre, selecione "Contas de serviço" e, em seguida, "Criar uma conta de serviço"



Digite o nome da conta e clique em "Criar"



Selecione a função Proprietário e clique em Continuar.



Na janela que aparece, clique em Criar chave



Selecione o tipo de chave json e clique em Criar



Um arquivo com chaves será criado e baixado imediatamente. Salve, graças a ele poderemos acessar os serviços do Google.

Clique no botão com três pinceladas horizontais, à esquerda da inscrição "APIs do Google", selecione "API e serviços" e, nele, o subitem "Painel de controle".



Na janela que se abre, clique em "Ativar API e serviços"



Digite "google drive" na barra de pesquisa e clique no serviço "Google Drive API"



Clique em Ativar



O site notificará que a API está ativada e avisará que as credenciais devem ser criadas. Ignore este aviso (já criamos uma conta de serviço).



Volte ao painel de controle



Na janela que se abre, clique em "Ativar API e serviços"



Digite "planilha" na barra de pesquisa e clique no serviço "Google Sheets API"



Verifique se esta API está conectada. Ele deve ser ativado automaticamente quando você conecta a API do Google Drive. Se estiver conectado, você verá o botão "Gerenciar API", caso contrário, o botão "Ativar". Ligue-o se necessário.

Da última vez, visite console.developers.google.com/cloud-resource-manager

Selecione o menu Configurações no seu projeto


Na janela que se abre, selecione "Contas de serviço" e copie e salve o endereço de email da conta de serviço. Será útil você dar acesso a tabelas.



Agora vamos prosseguir com a instalação das bibliotecas. Execute o comando no console

pip3 install --upgrade google-api-python-client 

e então

 pip3 install oauth2client 

É possível que, ao executar o segundo comando, você receba uma mensagem de que a biblioteca oauth2client já esteja instalada.

Vá para raw.githubusercontent.com/gsuitedevs/python-samples/master/sheets/quickstart/quickstart.py

Pressione o botão direito do mouse e selecione "Salvar como"



Salve o arquivo como quickstart.py

e execute-o com o comando

 python quickstart.py 

Uma nova página será aberta no navegador (talvez ela diga que a página é insegura, mas corajosamente vá em frente) e você terá que aceitar as condições.

Nisto, nosso caminho está completo.

Preenchendo e formatando uma tabela


Crie a primeira tabela

 #   import httplib2 import apiclient.discovery from oauth2client.service_account import ServiceAccountCredentials CREDENTIALS_FILE = 'seraphic-effect-248407-7ac2c44ec709.json' #     ,     #     credentials = ServiceAccountCredentials.from_json_keyfile_name(CREDENTIALS_FILE, ['https://www.googleapis.com/auth/spreadsheets', 'https://www.googleapis.com/auth/drive']) httpAuth = credentials.authorize(httplib2.Http()) #    service = apiclient.discovery.build('sheets', 'v4', http = httpAuth) #      4  API spreadsheet = service.spreadsheets().create(body = { 'properties': {'title': '  ', 'locale': 'ru_RU'}, 'sheets': [{'properties': {'sheetType': 'GRID', 'sheetId': 0, 'title': '  ', 'gridProperties': {'rowCount': 100, 'columnCount': 15}}}] }).execute() spreadsheetId = spreadsheet['spreadsheetId'] #    print('https://docs.google.com/spreadsheets/d/' + spreadsheetId) 

Se tudo ocorreu sem erros, um link para a tabela será exibido.

O identificador do arquivo é usado neste link, o salvamos na variável spreadsheetId e o usaremos no futuro.

Siga-o. O Google informará que você não tem acesso



Não solicite permissão! Você receberá uma notificação de que não é possível entregar uma carta de solicitação ao endereço que o próprio Google atribuiu à conta do sistema. Mas você não pode alterar este endereço. Talvez isso não funcione apenas no modo livre.

Mas podemos nos dar acesso através do Google Drive. Você precisa substituir my_test_address@gmail.com pelo seu.

 driveService = apiclient.discovery.build('drive', 'v3', http = httpAuth) #    Google Drive  3  API access = driveService.permissions().create( fileId = spreadsheetId, body = {'type': 'user', 'role': 'writer', 'emailAddress': 'my_test_address@gmail.com'}, #     fields = 'id' ).execute() 

Agora você tem acesso, não feche a tabela, nós a gerenciaremos e analisaremos imediatamente as alterações.

Cada documento possui seu próprio código - spreadsheetId - é exatamente o que é exibido na barra de endereços quando abrimos a tabela no navegador (no URL da página com a tabela aberta, ele fica entre "https://docs.google.com/spreadsheets/d/" e "/ edit # gid = 0").

Nós o salvamos na variável spreadsheetId e continuaremos a trabalhar com ele.

Primeiro, um pouco de teoria.

Em cada arquivo (planilha) há guias de planilhas (planilha).

Cada planilha possui seu próprio código numérico (sheetId). A primeira folha criada no documento tem esse ID igual a 0. As folhas restantes têm um ID diferente de zero muito diferente (ou seja, não são numeradas consecutivamente).

Certifique-se disso

 #   results = service.spreadsheets().batchUpdate( spreadsheetId = spreadsheetId, body = { "requests": [ { "addSheet": { "properties": { "title": "  ", "gridProperties": { "rowCount": 20, "columnCount": 12 } } } } ] }).execute() #   ,  Id   spreadsheet = service.spreadsheets().get(spreadsheetId = spreadsheetId).execute() sheetList = spreadsheet.get('sheets') for sheet in sheetList: print(sheet['properties']['sheetId'], sheet['properties']['title']) sheetId = sheetList[0]['properties']['sheetId'] print('     Id = ', sheetId) 

Algo parecido com isto aparecerá na tela:

0 Folha número um
415832263 Outra folha
Vamos usar uma planilha com Id = 0


De fato, a primeira planilha tem um ID zero e a segunda é numerada de maneira diferente.

Mais uma pergunta: como especificar intervalos de células. Aparentemente, as planilhas do Google foram desenvolvidas por diferentes equipes, sob a orientação de diferentes gerentes e com a ajuda de diferentes arquitetos. Porque as coordenadas das células são definidas de duas maneiras diferentes.

Opção 1: no formato de texto "Folha número um! B2: D5", ou seja, o nome da planilha, seguido de um ponto de exclamação, após - a célula superior esquerda no formato "letra (coluna) + número (string)" + a célula inferior direita no mesmo formato.

 {"range": "  !B2:D5"} 

Opção 2: no formato json, indicando o ID da planilha e as coordenadas das células superior esquerda e inferior direita em formato numérico (número da linha e número da coluna)

 {"range": { "sheetId": sheetId, # ID  "startRowIndex": 1, #    startRowIndex "endRowIndex": 5,#  endRowIndex - 1 (endRowIndex  !) "startColumnIndex": 0, #    startColumnIndex "endColumnIndex": 1 #  endColumnIndex - 1 }} 

Diferentes funções usam diferentes formatos.

Agora sabemos o suficiente para preencher as células com dados, desenhar um quadro e destacar os cabeçalhos.

 results = service.spreadsheets().values().batchUpdate(spreadsheetId = spreadsheetId, body = { "valueInputOption": "USER_ENTERED", #  ,    (  ) "data": [ {"range": "  !B2:D5", "majorDimension": "ROWS", #   ,   "values": [ [" B2", " C2", " D2"], #    ['25', "=6*6", "=sin(3,14/2)"] #    ]} ] }).execute() 

Preencha várias células com dados. Porque o parâmetro USER_ENTERED é especificado, a tabela percebe esses dados da mesma forma que perceberia a entrada do usuário - converte valores numéricos em números e valores começando com o sinal de igual em fórmulas.

Olhe para a sua mesa, ela está cheia de dados



Defina a largura da coluna. A função batchUpdate pode aceitar vários comandos ao mesmo tempo, portanto, definiremos a largura de três grupos de colunas com uma solicitação. Há uma coluna no primeiro e terceiro grupos e duas no segundo.

 results = service.spreadsheets().batchUpdate(spreadsheetId = spreadsheetId, body = { "requests": [ #    A: 20  { "updateDimensionProperties": { "range": { "sheetId": sheetId, "dimension": "COLUMNS", #    "startIndex": 0, #     "endIndex": 1 #    startIndex  endIndex - 1 (endIndex  !) }, "properties": { "pixelSize": 20 #    }, "fields": "pixelSize" # ,     pixelSize } }, #    B  C: 150  { "updateDimensionProperties": { "range": { "sheetId": sheetId, "dimension": "COLUMNS", "startIndex": 1, "endIndex": 3 }, "properties": { "pixelSize": 150 }, "fields": "pixelSize" } }, #    D: 200  { "updateDimensionProperties": { "range": { "sheetId": sheetId, "dimension": "COLUMNS", "startIndex": 3, "endIndex": 4 }, "properties": { "pixelSize": 200 }, "fields": "pixelSize" } } ] }).execute() 

Olhe para a tabela, as larguras das colunas foram alteradas.



Desenhe um quadro ao redor da mesa

 #   results = service.spreadsheets().batchUpdate( spreadsheetId = spreadsheetId, body = { "requests": [ {'updateBorders': {'range': {'sheetId': sheetId, 'startRowIndex': 1, 'endRowIndex': 3, 'startColumnIndex': 1, 'endColumnIndex': 4}, 'bottom': { #      'style': 'SOLID', #   'width': 1, #  1  'color': {'red': 0, 'green': 0, 'blue': 0, 'alpha': 1}}, #   'top': { #      'style': 'SOLID', 'width': 1, 'color': {'red': 0, 'green': 0, 'blue': 0, 'alpha': 1}}, 'left': { #      'style': 'SOLID', 'width': 1, 'color': {'red': 0, 'green': 0, 'blue': 0, 'alpha': 1}}, 'right': { #      'style': 'SOLID', 'width': 1, 'color': {'red': 0, 'green': 0, 'blue': 0, 'alpha': 1}}, 'innerHorizontal': { #       'style': 'SOLID', 'width': 1, 'color': {'red': 0, 'green': 0, 'blue': 0, 'alpha': 1}}, 'innerVertical': { #       'style': 'SOLID', 'width': 1, 'color': {'red': 0, 'green': 0, 'blue': 0, 'alpha': 1}} }} ] }).execute() 



Combine as células acima da tabela e insira o título nelas.

 #   A2:D1 results = service.spreadsheets().batchUpdate( spreadsheetId = spreadsheetId, body = { "requests": [ {'mergeCells': {'range': {'sheetId': sheetId, 'startRowIndex': 0, 'endRowIndex': 1, 'startColumnIndex': 1, 'endColumnIndex': 4}, 'mergeType': 'MERGE_ALL'}} ] }).execute() #    results = service.spreadsheets().values().batchUpdate(spreadsheetId = spreadsheetId, body = { "valueInputOption": "USER_ENTERED", #  ,    (  ) "data": [ {"range": "  !B1", "majorDimension": "ROWS", #   ,   "values": [[" " ] ]} ] }).execute() 



Defina o formato para as células do cabeçalho da tabela

 #    results = service.spreadsheets().batchUpdate( spreadsheetId = spreadsheetId, body = { "requests": [ { "repeatCell": { "cell": { "userEnteredFormat": { "horizontalAlignment": 'CENTER', "backgroundColor": { "red": 0.8, "green": 0.8, "blue": 0.8, "alpha": 1 }, "textFormat": { "bold": True, "fontSize": 14 } } }, "range": { "sheetId": sheetId, "startRowIndex": 1, "endRowIndex": 2, "startColumnIndex": 1, "endColumnIndex": 4 }, "fields": "userEnteredFormat" } } ] }).execute() 



Existe uma maneira fácil de descobrir qual largura ou cor você precisa definir para uma célula. Para fazer isso, basta formatar manualmente uma das células e ler suas propriedades.

 ranges = ["  !C2:C2"] # results = service.spreadsheets().get(spreadsheetId = spreadsheetId, ranges = ranges, includeGridData = True).execute() print(' ') print(results['properties']) print('\n  ') print(results['sheets'][0]['data'][0]['rowData'] ) print('\n ') print(results['sheets'][0]['data'][0]['rowMetadata']) print('\n ') print(results['sheets'][0]['data'][0]['columnMetadata']) 

Nós recebemos uma resposta
Dados mestre
{'title': 'Primeiro documento de teste', 'localidade': 'ru_RU', 'autoRecalc': 'ON_CHANGE', 'timeZone': 'Etc / GMT', 'defaultFormat': {'backgroundColor': {'red' : 1, 'verde': 1, 'azul': 1}, 'padding': {'top': 2, 'right': 3, 'bottom': 2, 'left': 3}, 'verticalAlignment': 'BOTTOM', 'wrapStrategy': 'OVERFLOW_CELL', 'textFormat': {'foregroundColor': {}, 'fontFamily': 'arial, sans, sans-serif', 'fontSize': 10, 'bold': False, 'itálico': falso, 'tachado': falso, 'sublinhado': falso}}}

Valores e coloração
[{'values': [{'userEnteredValue': {'stringValue': 'Cell C2'}, 'effectiveValue': {'stringValue': 'Cell C2'}, 'formattedValue': 'Cell C2', 'userEnteredFormat' : {'backgroundColor': {'red': 1, 'green': 0.6}, 'horizontalAlignment': 'CENTER', 'textFormat': {'fontSize': 14, 'bold': True, 'italic': True }}, 'effectiveFormat': {'backgroundColor': {'red': 1, 'green': 0,6}, 'padding': {'top': 2, 'right': 3, 'bottom': 2, ' left ': 3},' horizontalAlignment ':' CENTER ',' verticalAlignment ':' BOTTOM ',' wrapStrategy ':' OVERFLOW_CELL ',' textFormat ': {' foregroundColor ': {},' fontFamily ':' Arial ', 'fontSize': 14, 'bold': True, 'itálico': True, 'tachado': False, 'underline': False}, 'hyperlinkDisplayType': 'PLAIN_TEXT'}}]}]]

Altura da célula
[{'pixelSize': 21}]

Largura da célula
[{'pixelSize': 150}]
Este código exibirá as propriedades da célula C2. Você pode selecionar a fonte e preencher a cor manualmente (na tabela) e depois ver como elas são refletidas no json.

Lendo dados de uma tabela


Para revelar completamente os recursos da leitura de dados, preenchi manualmente as células B4, C7 e D5, como mostrado na figura.



Código para ler dados

 ranges = ["  !A2:F8"] # results = service.spreadsheets().values().batchGet(spreadsheetId = spreadsheetId, ranges = ranges, valueRenderOption = 'FORMATTED_VALUE', dateTimeRenderOption = 'FORMATTED_STRING').execute() sheet_values = results['valueRanges'][0]['values'] print(sheet_values) 

Resultado
[['', 'Célula B2', 'Célula C2', 'Célula D2'], ['', '25', '36', '0,9999996829']]

Alguns parâmetros da função: valueRenderOption - formato para leitura de dados numéricos.

  • FORMATTED_VALUE - leitura baseada no formato de exibição. I.e. o que estava visível na tabela será lido. Por exemplo, na célula D3, o número é 0,9999999, mas o formato é "duas casas decimais"; portanto, "1,00" é exibido; é nesse formato que será lido.
  • UNFORMATTED_VALUE - o conteúdo da célula é lido, a formatação não é levada em consideração (ou seja, 0,9999999 seria lido)
  • FÓRMULA - a fórmula é exibida (neste caso “= sin (3,14 / 2).” Se um número for inserido na célula, nesse modo, ele será lido.

Este código lê os dados e os exibe linha por linha. Faixa legível A2: F8.
Como visto na tela:

  • Se nenhuma célula na linha que está sendo lida for preenchida, os dados na linha não serão exibidos.
  • Os dados após a última célula preenchida não são exibidos.

Source: https://habr.com/ru/post/pt483302/


All Articles