My first attempt was to publish the Org files using the HTML backend then upload those into Google Drive and convert them to Google Docs. But the resulting Google Doc file was not very good. The links in the table of contents were not working at all, the formatting was off, etc.

My next attempt was to export as ODT files. This time the conversion to Google Docs was much better and had none of the issues the HTML files had. Satisfied with the conversion result, I quickly got to configuring my Orgmode project to use the ODT backend for publishing. But to my annoyance, the ox-odt.el package did not have a publishing function useable with org-publish-project-alist at all.

But with a little bit of digging and a lot of trial and error, I ended up with the following implementation of a publishing function for ODT:

1: ;;; ### autoload 2: ( defun org-odt-publish-to-odt ( plist filename pub-dir ) 3: "Publish an org file to ODT. 4: 5: FILENAME is the filename of the Org file to be published. PLIST 6: is the property list of the given project. PUB-DIR is the publishing 7: directory. 8: 9: Return output file name." 10: ( unless ( or ( not pub-dir ) ( file-exists-p pub-dir )) ( make-directory pub-dir t )) 11: ;; Check if a buffer visiting FILENAME is already open. 12: ( let* (( org-inhibit-startup t ) 13: ( visiting ( find-buffer-visiting filename )) 14: ( work-buffer ( or visiting ( find-file-noselect filename )))) 15: ( unwind-protect 16: ( with-current-buffer work-buffer 17: ( let (( outfile ( org-export-output-file-name ".odt" nil pub-dir ))) 18: ( org-odt--export-wrap 19: outfile 20: ( let* (( org-odt-embedded-images-count 0 ) 21: ( org-odt-embedded-formulas-count 0 ) 22: ( org-odt-object-counters nil ) 23: ( hfy-user-sheet-assoc nil )) 24: ( let (( output ( org-export-as 'odt nil nil nil 25: ( org-combine-plists 26: plist 27: ` ( :crossrefs 28: , ( org-publish-cache-get-file-property 29: ( expand-file-name filename ) :crossrefs nil t ) 30: :filter-final-output 31: ( org-publish--store-crossrefs 32: org-publish-collect-index 33: ,@ ( plist-get plist :filter-final-output )))))) 34: ( out-buf ( progn ( require ' nxml-mode ) 35: ( let (( nxml-auto-insert-xml-declaration-flag nil )) 36: ( find-file-noselect 37: ( concat org-odt-zip-dir "content.xml" ) t ))))) 38: ( with-current-buffer out-buf ( erase-buffer ) ( insert output )))))))) 39: ( unless visiting ( kill-buffer work-buffer ))))