importtimeimportgoogle.authfromgoogleapiclient.discoveryimportbuildfromgoogleapiclient.errorsimportHttpError# Fill-in IDs of your Docs template & any Sheets data sourceDOCS_FILE_ID="195j9eDD3ccgjQRttHhJPymLJUCOUjs-jmwTrekvdjFE"SHEETS_FILE_ID="11pPEzi1vCMNbdpqaQx4N43rKmxvZlgEHE9GqpYoEsWw"# authorization constantsSCOPES=(# iterable or space-delimited string"https://www.googleapis.com/auth/drive","https://www.googleapis.com/auth/documents","https://www.googleapis.com/auth/spreadsheets.readonly",)# application constantsSOURCES=("text","sheets")SOURCE="text"# Choose one of the data SOURCESCOLUMNS=["to_name","to_title","to_company","to_address"]TEXT_SOURCE_DATA=(("Ms. Lara Brown","Googler","Google NYC","111 8th Ave\nNew York, NY 10011-5201",),("Mr. Jeff Erson","Googler","Google NYC","76 9th Ave\nNew York, NY 10011-4962",),)# fill-in your data to merge into document template variablesmerge={# sender data"my_name":"Ayme A. Coder","my_address":"1600 Amphitheatre Pkwy\nMountain View, CA 94043-1351","my_email":"http://google.com","my_phone":"+1-650-253-0000",# - - - - - - - - - - - - - - - - - - - - - - - - - -# recipient data (supplied by 'text' or 'sheets' data source)"to_name":None,"to_title":None,"to_company":None,"to_address":None,# - - - - - - - - - - - - - - - - - - - - - - - - - -"date":time.strftime("%Y %B %d"),# - - - - - - - - - - - - - - - - - - - - - - - - - -"body":("Google, headquartered in Mountain View, unveiled the new ""Android phone at the Consumer Electronics Show. CEO Sundar ""Pichai said in his keynote that users love their new phones."),}creds,_=google.auth.default()# pylint: disable=maybe-no-member# service endpoints to Google APIsDRIVE=build("drive","v2",credentials=creds)DOCS=build("docs","v1",credentials=creds)SHEETS=build("sheets","v4",credentials=creds)defget_data(source):"""Gets mail merge data from chosen data source."""try:ifsourcenotin{"sheets","text"}:raiseValueError(f"ERROR: unsupported source {source}; choose from {SOURCES}")returnSAFE_DISPATCH[source]()exceptHttpErroraserror:print(f"An error occurred: {error}")returnerrordef_get_text_data():"""(private) Returns plain text data; can alter to read from CSV file."""returnTEXT_SOURCE_DATAdef_get_sheets_data(service=SHEETS):"""(private) Returns data from Google Sheets source. It gets all rows of 'Sheet1' (the default Sheet in a new spreadsheet), but drops the first (header) row. Use any desired data range (in standard A1 notation). """return(service.spreadsheets().values().get(spreadsheetId=SHEETS_FILE_ID,range="Sheet1").execute().get("values")[1:])# skip header row# data source dispatch table [better alternative vs. eval()]SAFE_DISPATCH={k:globals().get(f"_get_{k}_data")forkinSOURCES}def_copy_template(tmpl_id,source,service):"""(private) Copies letter template document using Drive API then returns file ID of (new) copy. """try:body={"name":f"Merged form letter ({source})"}return(service.files().copy(body=body,fileId=tmpl_id,fields="id").execute().get("id"))exceptHttpErroraserror:print(f"An error occurred: {error}")returnerrordefmerge_template(tmpl_id,source,service):"""Copies template document and merges data into newly-minted copy then returns its file ID. """try:# copy template and set context data struct for merging template valuescopy_id=_copy_template(tmpl_id,source,service)context=merge.iteritems()ifhasattr({},"iteritems")elsemerge.items()# "search & replace" API requests for mail merge substitutionsreqs=[{"replaceAllText":{"containsText":{"text":"{{%s}}"%key.upper(),# {{VARS}} are uppercase"matchCase":True,},"replaceText":value,}}forkey,valueincontext]# send requests to Docs API to do actual mergeDOCS.documents().batchUpdate(body={"requests":reqs},documentId=copy_id,fields="").execute()returncopy_idexceptHttpErroraserror:print(f"An error occurred: {error}")returnerrorif__name__=="__main__":# get row data, then loop through & process each form letterdata=get_data(SOURCE)# get data from data sourcefori,rowinenumerate(data):merge.update(dict(zip(COLUMNS,row)))print("Merged letter %d: docs.google.com/document/d/%s/edit"%(i+1,merge_template(DOCS_FILE_ID,SOURCE,DRIVE)))
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["没有我需要的信息","missingTheInformationINeed","thumb-down"],["太复杂/步骤太多","tooComplicatedTooManySteps","thumb-down"],["内容需要更新","outOfDate","thumb-down"],["翻译问题","translationIssue","thumb-down"],["示例/代码问题","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2024-12-21。"],[[["This guide demonstrates how to utilize the Google Docs API to execute a mail merge, automating the process of generating personalized documents from a template and data source."],["Users can choose between plain text or a Google Sheet as their data source, with the sample app providing examples for both options."],["The application copies a template document, merges variables from the data source, and outputs a link to the newly-merged document, accessible in Google Drive."],["Placeholder variables within the template document are replaced with data from the designated source, allowing for customization of individual documents."],["Refer to the GitHub repository for the complete source code, setup instructions, and further information on using the sample application."]]],[]]