File size: 5,152 Bytes
e6fad38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import os
import argparse
from google.oauth2 import service_account
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload
from googleapiclient.errors import HttpError
from typing import Optional, Tuple

SCOPES = ['https://www.googleapis.com/auth/drive']
MIMETYPE_EXCEL = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
MIMETYPE_SHEETS = 'application/vnd.google-apps.spreadsheet'

def get_drive_service(credentials_file: str):
    """Authenticates and returns the Google Drive service object."""
    try:
        creds = service_account.Credentials.from_service_account_file(
            credentials_file, scopes=SCOPES)
        return build('drive', 'v3', credentials=creds)
    except Exception as e:
        print(f"[ERROR] Authentication failed. Check your credentials file ({credentials_file}). Error: {e}")
        return None

def find_sheet(service, sheet_name: str, parent_folder_id: Optional[str]) -> Tuple[Optional[str], Optional[str]]:
    """Searches for an existing Google Sheet by name."""
    query = f"name='{sheet_name}' and mimeType='{MIMETYPE_SHEETS}' and trashed=false"
    
    if parent_folder_id:
        query += f" and '{parent_folder_id}' in parents"

    try:
        response = service.files().list(
            q=query,
            spaces='drive',
            fields='files(id, name)'
        ).execute()
        
        file_list = response.get('files', [])
        if file_list:
            return file_list[0]['id'], file_list[0]['name']
        return None, None
    except HttpError as error:
        print(f'[ERROR] An error occurred during file search: {error}')
        return None, None


def upload_excel_to_sheets(
    service, 
    file_id: Optional[str], 
    excel_filepath: str, 
    sheet_name: str, 
    parent_folder_id: Optional[str]
) -> Optional[str]:
    """Uploads an Excel file, converting it to a Google Sheet, or updates an existing one."""

    media = MediaFileUpload(
        excel_filepath,
        mimetype=MIMETYPE_EXCEL,
        resumable=True
    )
    
    file_metadata = {
        'name': sheet_name,
        'mimeType': MIMETYPE_SHEETS
    }
    
    if parent_folder_id and not file_id:
        file_metadata['parents'] = [parent_folder_id]

    if file_id:
        try:
            file = service.files().update(
                fileId=file_id,
                media_body=media,
                fields='id, webViewLink'
            ).execute()
            print(f"✅ Successfully UPDATED Google Sheet: {sheet_name}")
        except HttpError as error:
            print(f'[ERROR] An error occurred during file update (ID: {file_id}): {error}')
            return None
    else:
        try:
            file = service.files().create(
                body=file_metadata,
                media_body=media,
                fields='id, webViewLink'
            ).execute()
            print(f"✅ Successfully CREATED Google Sheet: {sheet_name}")
        except HttpError as error:
            print(f'[ERROR] An error occurred during file upload: {error}')
            return None

    return file.get('id')

def main():
    parser = argparse.ArgumentParser(
        description="Uploads the local Excel file to Google Sheets, updating or creating the document."
    )
    parser.add_argument(
        "--excel_path", 
        type=str, 
        default="./GRPO/Evaluation/metrics_summary.xlsx", 
        help="Path to the local Excel file."
    )
    parser.add_argument(
        "--run_name", 
        type=str, 
        required=True, 
        help="Run name (used as fallback for sheet title)."
    )
    parser.add_argument(
        "--credentials", 
        type=str, 
        default="service_account_credentials.json", 
        help="Path to the Google service account JSON key file."
    )
    parser.add_argument(
        "--folder_id", 
        type=str, 
        default=None, 
        help="Optional: ID of the Google Drive folder to upload to."
    )
    parser.add_argument(
        "--google_sheet_name", 
        type=str, 
        default=None, 
        help="The fixed name of the Google Sheet file (overrides derived name)."
    )
    args = parser.parse_args()

    # Use the explicit sheet name if provided, otherwise derive it from run_name
    if args.google_sheet_name:
        sheet_title = args.google_sheet_name
    else:
        sheet_title = f"Metrics Summary - {args.run_name}"

    if not os.path.exists(args.excel_path):
        print(f"Error: Excel file not found at {args.excel_path}. Run create_table.py first.")
        return

    if not os.path.exists(args.credentials):
        print(f"Error: Credentials file not found at {args.credentials}.")
        return

    service = get_drive_service(args.credentials)
    if not service:
        return
        
    file_id, found_name = find_sheet(service, sheet_title, args.folder_id)

    sheet_id = upload_excel_to_sheets(service, file_id, args.excel_path, sheet_title, args.folder_id)
    
    if sheet_id:
        print(f"\n🔗 Sheet URL: https://docs.google.com/spreadsheets/d/{sheet_id}/edit")


if __name__ == '__main__':
    main()