-1

I used Google Sheets to add points in Google My Maps. I know it is possible to add an image to the points. However, I have more than 600 points and I wonder if it is possible to add photos via image path in the spreadsheet?

Unfortunately, they are not geotagged...

3
  • If you mean add image to placemark icon, i already proposed a solution packing images in a kmz file and uploading it to My Maps if it's helpful gis.stackexchange.com/questions/425692/…
    – Pepe N O
    Mar 14, 2022 at 20:58
  • Google My Maps is your only option? I know a way to do what you are asking but in Google Earth Mar 15, 2022 at 12:59
  • Well, we are relatively limited in technical possibilities. I only want to publish coordinates with a name and a photo at each point and then implement this in a website. I found google sheets as a practical solution. But I am also fine with KMZ, or any other easy way. baumnaturdenkmal.at/webmap
    – parallax
    Mar 15, 2022 at 18:53

1 Answer 1

0

I have done this with an HTML+JavaScript page that "creates" kml code, reading a Google spreadsheet for populating the "kml text", here is the code and you have to put your own structure, and you can use simplehttpserver, I made a little script for waking the web server, you can find it at the end

<!DOCTYPE html>
<html>
 <head>
    <title> Spreadsheets to KML </title>
    <meta charset="utf-8"/>
</head>
<body>
    <p>Google Sheets to KML </p>

    <button id="authorize_button" style="display: none;">Autorizar</button>
    <button id="signout_button" style="display: none;">Salir</button>

    <pre id="content" style="white-space: pre-wrap;"></pre>

    <script type="text/javascript">
        //Client ID and API key from the Developer Console
        var CLIENT_ID = 'YourGoogleCloudClientID';
        var API_KEY = 'YourSheetsApiKey';

        //Array of API discovery doc URLs for APIs used by the quickstart
        var DISCOVERY_DOCS = ["https://sheets.googleapis.com/$discovery/rest?version=v4"];

        //Autorization scopes required by the API; multiple scopes can be included, separated by spaces.
        var SCOPES = "https://www.googleapis.com/auth/spreadsheets.readonly";

        var authorizeButton = document.getElementById('authorize_button');
        var signoutButton = document.getElementById('signout_button');

        /**
         * On load, called to load the auth2 library and API client library.
         * 
         */
        function handleClientLoad() {
            gapi.load('client:auth2', initClient);
        }

        /**
         * Initializes the API client library and sets up sign-in state listeners
         */
        function initClient() {
            gapi.client.init({
                apiKey : API_KEY,
                clientId : CLIENT_ID,
                discoveryDocs : DISCOVERY_DOCS,
                scope : SCOPES
            }).then(function (){
                //Listen for sign-in state changes.
                gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);

                //Handle the initial sign-in state.
                updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
                authorizeButton.onclick = handleAuthClick;
                signoutButton.onclick = handleSignOutClick;
            }, function(error) {
                appendPre(JSON.stringify(error, null, 2));
            })
        }

        /**
         * Called when the signed in status changes, to update the UI
         * appropriately. After a sign-in, the API is called.
         */
        function updateSigninStatus(isSignedIn) {
            if(isSignedIn) {
                authorizeButton.style.display = 'none';
                signoutButton.style.display = 'block';
                listPatrollingPoints();
            } else {
                authorizeButton.style.display = 'block';
                signoutButton.style.display = 'none';
            }
        }

        /**
         * Sign in the user upon button click.
         */
        function handleAuthClick(event) {
            gapi.auth2.getAuthInstance().signIn();
        }

        /**
         * Sign out the user upon button click
         */
        function handleSignOutClick(event) {
            gapi.auth2.getAuthInstance().signOut();
        }

        /**
         * Append a pre element to the body containing the given message
         * as its text node. Used to display the results of the API call.
         * 
         * @param {string} message Text to ve placed in pre element.
         */
        function appendPre(message) {
            var pre = document.getElementById('content');
            var textContent = document.createTextNode(message + '\n');
            pre.appendChild(textContent);
        }

        /**
         * Print the Date and Coordinates in a spreadsheet:
         * https://docs.google.com/spreadsheets/d/YOURSHEETID/
         */
        function listPatrollingPoints() {
            gapi.client.sheets.spreadsheets.values.get({
                spreadsheetId : 'YOURSHEETID',
                range : 'SheetName!Range',
            }).then(function(response) {
                var range = response.result;
                if(range.values.length > 0) {                                                
                    appendPre('<?xml version="1.0" encoding="UTF-8"?>');
                    appendPre('<kml xmlns="http://www.opengis.net/kml/2.2">');
                    appendPre('<Document>');
                    appendPre('<Folder>');    
                    for (i=0; i<range.values.length; i++) {
                        var row = range.values[i];
                        appendPre('<Placemark>');
                        appendPre('<name>'+ row[1] + '</name>');    
                        appendPre('<description><![CDATA[<img style="max-width:500px;" src="'+ row[4] +'">Inspector:'+ row[3] +']]></description>');                            
                        appendPre('<Point>');
                        appendPre('<coordinates>');    
                        appendPre(row[7] + ', ' + row[6] + ', 0');
                        appendPre('</coordinates>');
                        appendPre('</Point>');
                        appendPre('</Placemark>');
                    }
                    appendPre('</Folder>');
                    appendPre('</Document>');
                    appendPre('</kml>');
                } else {
                    appendPre('No data found');
                }
            }, function(response) {
                appendPre('Error: ' + response.result.error.message);
            });
        }

        </script>

        <script async defer src="https://apis.google.com/js/api.js" onload="this.onload=function(){};handleClientLoad()" onreadystatechange="if(this.readyState == 'complete') this.onload()">
        </script>
</body>
</html>

The tiny script (cmd script) for the web server is (im assuming that only reading it you will know what im talking about, so if you have doubts only ask):

@echo off
python -m http.server.8000

From here you access to the web page by the URL http://localhost:8000/ and copy the text with MKL structure to a empty file named doc.kml. You must have the image folder in the same folder of the KML file, then you can add the doc.kml file and the image folder to a zip file, then the generated zip file must be renamed with the kmz extension.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.