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.')