11import argparse
22import gspread
3+ from io import BytesIO
34import logging
5+ from openpyxl import Workbook
46import requests
57from pathlib import Path
68from google .oauth2 import service_account
911logger = logging .getLogger (__name__ )
1012
1113
14+ # TODO: class for google service
15+
16+
1217def get_sheets_service_and_token (credentials_file = "credentials.json" ):
1318 """Создает и возвращает сервис для работы с Google Sheets и API access_token"""
1419 creds = service_account .Credentials .from_service_account_file (
@@ -32,30 +37,69 @@ def download_sheet(
3237 write_to_file = True ,
3338) -> bytes | None :
3439 try :
35- _ , access_token = get_sheets_service_and_token (google_cred )
36-
37- url = f"https://docs.google.com/spreadsheets/d/{ table_id } /export?format={ export_format } &gid={ sheet_id } "
38-
39- response = requests .get (
40- url , headers = {"Authorization" : f"Bearer { access_token } " }
41- )
42-
43- if response .status_code == 200 :
44- content = response .content
45- if write_to_file :
46- new_filepath = Path (f"{ filename } .{ export_format } " )
47- new_filepath .parents [0 ].mkdir (parents = True , exist_ok = True )
48- with open (new_filepath , "wb" ) as f :
49- f .write (content )
50- logger .debug (f"download_sheet. Файл сохранен как: { new_filepath } " )
51- return content
40+ client , access_token = get_sheets_service_and_token (google_cred )
41+ if export_format == "xlsx" :
42+ content = get_excel_with_values (client , table_id , sheet_id )
5243 else :
53- logger .error (f"Ошибка { response .status_code } : { response .text } " )
44+ content = export_file (table_id , sheet_id , access_token , export_format )
45+
46+ if not content :
47+ logger .error (f"Ошибка экспорта файла" )
48+ return None
49+
50+ if write_to_file :
51+ new_filepath = Path (f"{ filename } .{ export_format } " )
52+ new_filepath .parents [0 ].mkdir (parents = True , exist_ok = True )
53+ with open (new_filepath , "wb" ) as f :
54+ f .write (content )
55+ logger .debug (f"Файл сохранен как: { new_filepath } " )
56+ return content
5457
5558 except Exception as e :
5659 logger .error (f"Ошибка при скачивании: { e } " )
5760
5861
62+ def get_excel_with_values (
63+ service : gspread .Client , table_id : str , sheet_id : str
64+ ) -> bytes :
65+ """
66+ Сохраняет значения (не формулы) листа таблицы в XLSX-файл
67+ """
68+ spreadsheet = service .open_by_key (table_id )
69+ worksheet = spreadsheet .get_worksheet_by_id (int (sheet_id ))
70+ data = worksheet .get_all_values ()
71+
72+ wb = Workbook ()
73+ ws = wb .active
74+ ws .title = worksheet .title
75+
76+ for row in data :
77+ ws .append (row )
78+
79+ file_stream = BytesIO ()
80+ wb .save (file_stream )
81+ file_stream .seek (0 )
82+
83+ return file_stream .read ()
84+
85+
86+ def export_file (
87+ table_id : str , sheet_id : str , access_token : str , export_format : str
88+ ) -> bytes | None :
89+ """
90+ Экспортирует файл используя export-url
91+ """
92+ url = f"https://docs.google.com/spreadsheets/d/{ table_id } /export?format={ export_format } &gid={ sheet_id } "
93+
94+ response = requests .get (url , headers = {"Authorization" : f"Bearer { access_token } " })
95+
96+ if response .status_code == 200 :
97+ return response .content
98+ else :
99+ logger .error (f"export_file: Ошибка { response .status_code } : { response .text } " )
100+ return None
101+
102+
59103def parse_args ():
60104 parser = argparse .ArgumentParser (description = "Download Google Sheets" )
61105 parser .add_argument ("--table_id" , required = True , help = "Google Sheets table ID" )
0 commit comments