Use LaTeX, SVG and EMF Files in Google Slides

Sep 13, 2023

While very annoying, Google Slides does not naturally support vector graphics as of now. The workaround is to upload and convert a vector graphic to Google Drawing, copy the image from Drawing and paste into Slides. As of now, Drawing only supports EMF or WMF, which can be converted to with Inkscape relatively quickly.

Even more annoyingly, you cannot directly upload an EMF file through web interface and have Google convert it for you. You have to use Google API for that for some reason, so I write a short script for the purpose:

import argparse import google.auth from googleapiclient.discovery import build from googleapiclient.http import MediaFileUpload # authenticate with sudo snap install google-cloud-cli --classic # and then # gcloud auth application-default login --scopes='https://www.googleapis.com/auth/drive','https://www.googleapis.com/auth/cloud-platform' # (create a random project on Google Cloud for billing) # gcloud auth application-default set-quota-project def get_folder(service, name): page_token = None while True: # pylint: disable=maybe-no-member response = ( service.files() .list( q="mimeType = 'application/vnd.google-apps.folder'", spaces="drive", fields="nextPageToken, " "files(id, name)", pageToken=page_token, ) .execute() ) for file in response.get("files", []): if file.get("name") == name: return file.get("id") page_token = response.get("nextPageToken", None) if page_token is None: break print(f"INFO: Cannot find folder named {name} in the Drive. Creating...") file_metadata = { "name": name, "mimeType": "application/vnd.google-apps.folder", } file = service.files().create(body=file_metadata, fields="id").execute() return file.get("id") if __name__ == "__main__": parser = argparse.ArgumentParser( prog="uploademf", description="Upload *.emf file to Google Drive and convert to Google Drawing", ) parser.add_argument("folder") parser.add_argument("filename") args = parser.parse_args() creds, _ = google.auth.default() # create drive api client service = build("drive", "v3", credentials=creds) # find out admissible file types # print(service.about().get(fields='importFormats').execute()) # print(service.about().get(fields='exportFormats').execute()) folder_id = get_folder(service, args.folder) print(f"INFO: Found folder {args.folder} with id {folder_id}...") file_metadata = { # .wmf is also permissible "name": args.filename, "mimeType": "application/vnd.google-apps.drawing", "parents": [folder_id], } media = MediaFileUpload( args.filename, mimetype="application/x-msmetafile", resumable=True ) file = ( service.files() .create(body=file_metadata, media_body=media, fields="id") .execute() ) print(f'INFO: File {args.filename} with ID: "{file.get("id")}" has been uploaded.')