Reads a CV PDF and writes what it says onto a fresh copy of your own Google Docs CV template.
Uses
Google Docs
Google Drive
OpenAI
Put a CV onto your own template
Give it a CV as a PDF and a link to your own Google Docs CV template, and run it. The CV is read section by section, a copy of your template is made in Drive named after the candidate, and each placeholder in the copy is replaced with the matching section of the CV.
You end up with a filled copy and an untouched template. An AI reads the CV and is told to copy each section word for word and never add or guess, so a placeholder gets text from the CV or the phrase 'Not stated in the CV' where a section is absent; as with any AI step, check the copy against the CV before you send it on. The AI is also told to leave out a date of birth, age, nationality, gender or marital status, even inside the contact details, and only text is written, so a photograph never comes across. A section your template has no placeholder for is written out at the end of the copy under a heading naming the placeholder to add, rather than being quietly lost.
You need OpenAI, Google Drive and Google Docs connected, the CV as a PDF, and the link to your template with a placeholder for each section in double curly braces, such as {{full_name}} or {{work_experience}}, wherever you want that section to land.
cvFileLink to blank.Set cvFileLink to blank.cvTemplateDocumentLink to blank.Set cvTemplateDocumentLink to blank.cvFileLink and save it as cvFile.Trim cvFileLink and save it as cvFile.cvTemplateDocumentLink and save it as templateLink.Trim cvTemplateDocumentLink and save it as templateLink.cvFile starts with http (ignoring case) or cvFile starts with doc_…If cvFile starts with http (ignoring case) or cvFile starts with doc_…cvFile contains docs.google.com (ignoring case) or cvFile contains…If cvFile contains docs.google.com (ignoring case) or cvFile contains…templateLink doesn't contain /d/If templateLink doesn't contain /d/cvFieldNames to [full name, contact details, personal profile, skills, work experience, education, certifications, languages].Set cvFieldNames to [full name, contact details, personal profile, skills, work experience, education, certifications, languages].extractedFields to an empty list.Set extractedFields to an empty list.readErrorIf a step below fails, save the error as readErrorcvFieldNa… and save it as extraction.Run an AI agent: Read the attached document and pull out each of these fields, in this order: - cvFieldNa… and save it as extraction.extraction.output.fields is emptyIf extraction.output.fields is emptyextractedFields to extraction.output.fields.Change extractedFields to extraction.output.fields.readError.message.Stop and report a problem: Could not read that CV, so no copy of your template has been made. The reason given was: readError.message.candidateName to blank.Set candidateName to blank.namedField in extractedFields:For each namedField in extractedFields:namedFieldName to blank.Set namedFieldName to blank.nameFieldErrorIf a step below fails, save the error as nameFieldErrornamedField.name lowercase and save it as namedFieldName.Make namedField.name lowercase and save it as namedFieldName.namedFieldName to blank.Change namedFieldName to blank.namedFieldName is full nameIf namedFieldName is full namenameValueErrorIf a step below fails, save the error as nameValueErrornamedField.value and save it as candidateName.Trim namedField.value and save it as candidateName.namedField.value with a space and save it as candidateName.Join namedField.value with a space and save it as candidateName.candidateName is emptyIf candidateName is emptycandidateName to Unnamed candidate.Change candidateName to Unnamed candidate.newCvLink to blank.Set newCvLink to blank.copyErrorIf a step below fails, save the error as copyErrortemplateLink. Save it as copy.Duplicate templateLink. Save it as copy.copy.duplicate_link and save it as newCvLink.Trim copy.duplicate_link and save it as newCvLink.copyError.message.Stop and report a problem: Could not copy your template, so nothing has been written. Your own template has not been touched. The reason given was: copyError.message.newCvLink doesn't contain /d/If newCvLink doesn't contain /d/newCvLink split by /d/ split by / and save it as newCvId.Get the first item of the last item of newCvLink split by /d/ split by / and save it as newCvId.sectionsWithNoPlace to an empty list.Set sectionsWithNoPlace to an empty list.sectionsNotInCv to an empty list.Set sectionsNotInCv to an empty list.wantedField in cvFieldNames:For each wantedField in cvFieldNames:placeholder to {{wantedField with replaced by _}}.Set placeholder to {{wantedField with replaced by _}}.fieldValue to blank.Set fieldValue to blank.extractedField in extractedFields:For each extractedField in extractedFields:extractedName to blank.Set extractedName to blank.extractedNameErrorIf a step below fails, save the error as extractedNameErrorextractedField.name lowercase and save it as extractedName.Make extractedField.name lowercase and save it as extractedName.extractedName to blank.Change extractedName to blank.extractedName is wantedFieldIf extractedName is wantedFieldextractedValueErrorIf a step below fails, save the error as extractedValueErrorextractedField.value and save it as fieldValue.Trim extractedField.value and save it as fieldValue.extractedField.value with a new line and save it as fieldValue.Join extractedField.value with a new line and save it as fieldValue.valueToWrite to fieldValue.Set valueToWrite to fieldValue.fieldValue is emptyIf fieldValue is emptyvalueToWrite to Not stated in the CV.Change valueToWrite to Not stated in the CV.wantedField to the end of sectionsNotInCv and save it as sectionsNotInCv.Add wantedField to the end of sectionsNotInCv and save it as sectionsNotInCv.landed to false.Set landed to false.replaceErrorIf a step below fails, save the error as replaceErrorplaceholder with valueToWrite in newCvId. Save it as replaceResult.Replace placeholder with valueToWrite in newCvId. Save it as replaceResult.occurrences to replaceResult.occurrences_changed multiplied by 1.Set occurrences to replaceResult.occurrences_changed multiplied by 1.occurrences is greater than or equal to 1 and occurrences is less than or…If occurrences is greater than or equal to 1 and occurrences is less than or…landed to true.Change landed to true.landed to false.Change landed to false.landed is no and fieldValue isn't emptyIf landed is no and fieldValue isn't emptywantedField - add placeholder to your templateAdd wantedField - add placeholder to your template
fieldValue to the end of sectionsWithNoPlace and save it as sectionsWithNoPlace.sectionsWithNoPlace and save it as noPlaceCount.Count the items in sectionsWithNoPlace and save it as noPlaceCount.noPlaceCount is greater than 0If noPlaceCount is greater than 0newCvId.Add text to newCvId.FROM THE CV BUT NOT PLACED
Your template has no placeholder for the sections below, so they are written out here rather than dropped. Add the placeholder named beside each heading to your template and run it again to have them filled in place.
sectionsWithNoPlace joined by a b...candidateName onto a copy of your template: newCvLinkShow in the output: Wrote the CV of candidateName onto a copy of your template: newCvLink
Sections your template had no placeholder for, written out at the end instead: noPlaceCount
Sections the CV does not contain, marked as not stated: sectionsNotInCv joined by , .