API

สร้างเว็บไซต์แสดงพิกัดบน Map โดยใช้ Google Spreadsheet เก็บข้อมูลอย่างง่าย

หากเรามีโจทย์ที่จะทำระบบแสดงข้อมูลพิกัดบนแผนที่บนเว็บไซต์ สิ่งที่เราต้องจัดเตรียมก็มีทั้ง ส่วนการพัฒนาเว็บไซต์ (HTML, JavaScript ฯลฯ) สำหรับแสดงผลแผนที่โดยใช้ Map API และต้องมีฐานข้อมูลเพื่อเก็บข้อมูลเหล่านั้นพร้อมกับ Service API ที่จะให้บริการข้อมูลจากฐานข้อมูลมาสู่หน้าเว็บไซต์ของเรา ซึ่งจะเห็นได้ว่ามีสิ่งที่เราต้องเตรียมการหลายส่วน

แต่วันนี้ Longdo Map จะมาแนะนำวิธีการเก็บข้อมูลพิกัดสถานที่ด้วย Google Spreadsheet ซึ่งเปรียบเสมือนเป็นระบบฐานข้อมูลของเรา และพร้อมที่จะให้บริการข้อมูลจาก Google Spreadsheet ในรูปแบบ Web Service API ไปแสดงผลบนเว็บไซต์แผนที่ รวมถึงการส่งข้อมูลพิกัดใหม่ไปบันทึกที่ Google Spreadsheet ด้วย

การสร้างข้อมูลพิกัดและดึงข้อมูลบน Google Spreadsheets

1. ทำการสร้างข้อมูลผ่าน https://docs.google.com/spreadsheets/ โดยจะต้องมีการสร้าง field ที่มีค่า latitude, longitude (สามารถตั้งชื่อ Column ได้อิสระ) สำหรับการกำหนดตำแหน่งของหมุด ทั้งนี้สามารถสร้าง field อื่นๆ ของแต่ละพิกัดได้อย่างอิสระ เช่น name, address เพื่อเป็นข้อมูลสำหรับแสดงรายละเอียดของพิกัดบน Popup ขณะที่กดไปยังหมุดนั้นๆ

พิกัดโรงพยาบาล จากเว็บไซต์แสดงข้อมูลเปิด (Open Data) โรงพยาบาล

2. เมื่อสร้างข้อมูลเสร็จแล้ว เราจะมาดำเนินการสร้าง Web Service API ที่ให้บริการข้อมูลของเรา โดยไปที่เมนู ส่วนขยาย -> Apps script หลังจากนั้นแก้ไขโค้ดดังตัวอย่าง

var ss = SpreadsheetApp.openById('[SHEET-ID]')
var sheet = ss.getSheetByName('[SHEET-NAME]')


function doGet(e) {
  var action = e.parameter.action
  if (action == 'getLocation') {
    return getLocation(e)
  }
}


function getLocation(e) {
  var rows = sheet.getRange(2,1,sheet.getLastRow()-1,sheet.getLastColumn()).getValues()
  var data =[]
  for(var i=0; i<rows.length;i++){
    var row = rows[i]
    var record = {}
    record['id']=row[0]
    record['depart']=row[1]
    record['sub_depart']=row[2]
    record['name']=row[3]
    record['address']=row[4]
    record['lat']=row[5]
    record['lon']=row[6]
    data.push(record)
  }
  var result = JSON.stringify(data)
  return ContentService.createTextOutput(result).setMimeType(ContentService.MimeType.JSON)
}

3. ในบรรทัดที่ 1 แก้ไข [SHEET-ID] โดยเอามาจาก URL ของหน้า Spreadsheets ข้อที่ 1 โดยนำมาเฉพาะส่วนที่ไฮไลต์เท่านั้น เช่น จากรูป [SHEET-ID] ก็คือ 1C8mqgsmfBNE3-ORYSwmaXCVCZn8TGIjLGaYGrhkzp7s

4. แก้ไข [SHEET-NAME] โดยเอามาจากชื่อของ spreadsheets ในข้อที่ 1 เช่นจากรูป [SHEET-NAME] ก็คือ Longdo Map – Sheet1

5. ไปที่ปุ่ม การทำให้ใช้งานได้ (อยู่ด้านบนขวาของหน้าต่าง) หลังจากนั้นให้เลือก การทำให้ใช้งานได้รายการใหม่

6. เลือกประเภทให้เป็น เว็บแอป ตั้งชื่อคำอธิบายใหม่ แก้ไขผู้ที่มีสิทธิ์เข้าถึงให้เป็น ทุกคน หลังจากนั้น กด การทำให้ใช้งานได้

7. คัดลอก เว็บแอป URL

8. เราจะลองทดสอบบริการข้อมูลว่าใช้งานได้หรือไม่ โดยการลองนำ URL ที่คัดลอกมาใส่ลงใน Searchbar ของ Web Browser แล้วเติม ?action=getLocation ซึ่งจะได้ URL ที่มีลักษณะประมาณนี้ https://script.google.com/macros/s/xxx/exec?action=getLocation

ผลลัพธ์ควรจะเป็นไปตามข้อมูลในข้อที่ 1 โดยอยู่ในรูปแบบ json

พิกัดโรงพยาบาล จากเว็บไซต์แสดงข้อมูลเปิด (Open Data) โรงพยาบาล

9. ต่อมาเราจะทำส่วนการแสดงผลพิกัดบนแผนที่ โดยสร้างไฟล์ html ขึ้นมา แล้วเรียกใช้แผนที่ตามตัวอย่างด้านล่าง

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>Longdo Map Spreadsheet | Longdo Map</title>
        <style type="text/css">
            html {
                height: 100%;
            }

            body {
                margin: 0px;
                height: 100%;
            }

            #map {
                height: 100%;
            }
        </style>
        <script
            type="text/javascript"
            src="https://api.longdo.com/map3/?key=[YOUR-API-KEY]"
        ></script>
        <script>
            var map;
            var hospital_list_ggsheet = [];
            function init() {
                map = new longdo.Map({
                    placeholder: document.getElementById("map"),
                });
                getSpreadsheet();
            }
            function getSpreadsheet() {
                var request = new XMLHttpRequest();
                request.open(
                    "GET",
                    "[YOUR-SCRIPT-URL]?action=getLocation",
                    true
                );

                request.onload = function () {
                    if (this.status >= 200 && this.status < 400) {
                        // Success!
                        var response = JSON.parse(this.response);
                        drawLocation(response);
                    } else {
                        // We reached our target server, but it returned an error
                    }
                };
                request.onerror = function () {
                    // There was a connection error of some sort
                };
                request.send();
            }
            function drawLocation(arr) {
                arr.forEach((location) => {
                    map.Overlays.add(
                        new longdo.Marker(
                            {
                                lon: Number(location.lon),
                                lat: Number(location.lat),
                            },
                            {
                                title: location.name,
                                detail: location.address,
                            }
                        )
                    );
                });
            }
        </script>
    </head>

    <body onload="init();">
        <div id="map"></div>
    </body>
</html>

อย่าลืมแก้ไข [YOUR-API-KEY] ให้เป็นคีย์ที่ได้จากการสมัครจาก Longdo Map Console และ [YOUR-SCRIPT-URL] ให้เป็น URL ที่ได้มาจาก Apps Script ที่ได้มาจากข้อ 7

เพียงเท่านี้เราก็จะได้แผนที่ตำแหน่งของโรงพยาบาล โดยที่ Popup หัวข้อจะเป็นชื่อโรงพยาบาล และ คำอธิบายจะเป็น ตำแหน่งของโรงพยาบาล

พิกัดโรงพยาบาล จากเว็บไซต์แสดงข้อมูลเปิด (Open Data) โรงพยาบาล

10. หากต้องการให้ เมื่อกดไปที่แผนที่แล้ว สามารถเพิ่มข้อมูลหมุดใหม่ลงบนแผนที่และบันทึกข้อมูลลงใน Spreadsheet ให้เริ่มจากการสร้าง function (ที่ไฟล์ html ข้อ 9) ซึ่งใช้ในการรับชื่อและข้อมูลของสถานที่ ที่เว็บไซต์ของเรา (สำหรับวิธีทำให้ข้อมูลไปบันทึกใน Spreadsheet จะกล่าวในข้อ 11)

function addLocation() {
                let text;
                let title = prompt("Please enter location name:");
                let detail = prompt("Please enter location detail:");
                return { title, detail };
}

หลังจากนั้นให้สร้าง Event Click (ที่ไฟล์ html ข้อ 9) ซึ่งใช้สำหรับสร้างหมุด

map.Event.bind("click", function () {
                    var mouseLocation = map.location(
                        longdo.LocationMode.Pointer
                    );
                    var location = addLocation();
                    map.Overlays.add(
                        new longdo.Marker(mouseLocation, location)
                    );
});

ตัวอย่างโค้ดเมื่อดำเนินการตามข้อ 9 – 10 เรียบร้อยแล้ว

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>Longdo Map Spreadsheet | Longdo Map</title>
        <style type="text/css">
            html {
                height: 100%;
            }

            body {
                margin: 0px;
                height: 100%;
            }

            #map {
                height: 100%;
            }
        </style>
        <script
            type="text/javascript"
            src="https://api.longdo.com/map3/?key=[YOUR-API-KEY]"
        ></script>
        <script>
            var map;
            var hospital_list_ggsheet = [];
            function init() {
                map = new longdo.Map({
                    placeholder: document.getElementById("map"),
                });
                map.Event.bind("click", function () {
                    var mouseLocation = map.location(
                        longdo.LocationMode.Pointer
                    );
                    var location = addLocation();
                    map.Overlays.add(
		new longdo.Marker(mouseLocation, {
        			title: location.name,
                		detail: location.address,
        		})
);
                });
                getSpreadsheet();
            }
            function getSpreadsheet() {
                var request = new XMLHttpRequest();
                request.open(
                    "GET",
                    "[YOUR-SCRIPT-URL]?action=getLocation",
                    true
                );

                request.onload = function () {
                    if (this.status >= 200 && this.status < 400) {
                        // Success!
                        var response = JSON.parse(this.response);
                        drawLocation(response);
                    } else {
                        // We reached our target server, but it returned an error
                    }
                };
                request.onerror = function () {
                    // There was a connection error of some sort
                };
                request.send();
            }
            function drawLocation(arr) {
                arr.forEach((location) => {
                    map.Overlays.add(
                        new longdo.Marker(
                            {
                                lon: Number(location.lon),
                                lat: Number(location.lat),
                            },
                            {
                                title: location.name,
                                detail: location.address,
                            }
                        )
                    );
                });
            }
            function addLocation() {
                let text;
                let name = prompt("Please enter location name:");
                let address = prompt("Please enter location detail:");
                return { name, address };
            }
        </script>
    </head>

    <body onload="init();">
        <div id="map"></div>
    </body>
</html>

อย่าลืมแก้ไข [YOUR-API-KEY] ให้เป็นคีย์ที่ได้จากการสมัครจาก Longdo Map Console และ [YOUR-SCRIPT-URL] ให้เป็น URL ที่ได้มาจาก Apps Script ที่ได้มาจากข้อ 7

11. เพื่อให้ข้อมูลที่เพิ่มบันทึกไปยัง Spreadsheet เราสามารถทำได้ดังนี้
ให้เพิ่มโค้ดส่วนนี้ไปที่ Apps Script

function doPost(e) {
  var action = e.parameter.action
  if (action == 'addLocation') {
    return addLocation(e)
  }
}

function addLocation(e) {
  var newLocation = JSON.parse(e.postData.contents)
  var lastRow = sheet.getLastRow();
  var lastCellId = sheet.getRange(sheet.getLastRow()-1, 1);
  sheet.appendRow([lastCellId.value()+1, “depart”, “sub_depart”, newLocation.name, newLocation.address, newLocation.lat, newLocation.lon])
  return ContentService.createTextOutput("success").setMimeType(ContentService.MimeType.TEXT)
}

เราสามารถตั้งค่า id, depart, sub_depart เพิ่มเติมได้โดยอาจจะเพิ่ม prompt ในข้อที่ 10 หรือจะทำ form ก็ได้ ตัวอย่างในข้อนี้เพิ่มแค่เพียง ชื่อ, ตำแหน่ง, ละติจูด, ลองติจูดเท่านั้น

12. เพิ่ม การทำให้ใช้งานได้ (วิธีเดียวกับข้อ 5-8) หรือเรากดที่ จัดการการทำให้ใช้งานได้ หลังจากนั้นกด แก้ไข แล้วกำหนดเวอร์ชันเป็น เวอร์ชันใหม่

13. เลือกประเภทให้เป็น เว็บแอป ตั้งชื่อคำอธิบายใหม่ แก้ไขผู้ที่มีสิทธิ์เข้าถึงให้เป็น ทุกคน หลังจากนั้น กด การทำให้ใช้งานได้ (แนะนำให้ตั้งชื่อต่างจากข้อที่ 6 จะได้แยกแยะถูกเพราะ URL ในข้อที่ 6 จะไม่สามารถเพิ่มจุดได้ จำเป็นต้องแก้ไขหรือสร้าง URL ใหม่ทุกครั้งที่มีการแก้ไขใน Apps Script)

14. ในกรณีที่เพิ่มการทำให้ใช้งานได้ ให้นำ URL ที่ได้มาใหม่ ไปแทนที่ URL เก่า (ยังมี ?action=getLocation ต่อท้ายเหมือนเดิม) ลักษณะจะเป็นประมาณนี้ https://script.google.com/macros/s/xxx/exec?action=getLocation หลังจากนั้น ให้เพิ่มการเรียก api สำหรับการเพิ่มจุดลงไปในโค้ด โดยที่ URL สำหรับการเพิ่มจุดให้ใช้ ?action=addLocation ลักษณะจะประมาณนี้
https://script.google.com/macros/s/xxx/exec?action=addLocation สังเกตว่าสิ่งที่แตกต่างกันมีเพียง getLocation และ addLocation

การแก้ไขโค้ดใน App Scripts จำเป็นต้อง เพิ่มการทำให้ใช้งานได้ หรือ จัดการการทำให้ใช้งานได้ การแก้ไขโค้ดแล้วใช้ URL เดิมจะไม่ได้ผลลัพธ์ที่แก้ไป

ตัวอย่างโค้ดสำเร็จรูป สังเกตว่าเราจะไม่มีการ Overlays.add เนื่องจากมีการตำแหน่งใน spreadsheet แล้วเรียก เพื่ออัพเดทจุดแทน ตัวอย่างนี้ยังมี ตัวอย่างการเพิ่ม depart กับ sub_depart ด้วย

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title>Longdo Map Spreadsheet | Longdo Map</title>
        <style type="text/css">
            html {
                height: 100%;
            }

            body {
                margin: 0px;
                height: 100%;
            }

            #map {
                height: 100%;
            }
        </style>
        <script
            type="text/javascript"
            src="https://api.longdo.com/map3/?key=[YOUR-API-KEY]"
        ></script>
        <script>
            var map;
            var hospital_list_ggsheet = [];
            function init() {
                map = new longdo.Map({
                    placeholder: document.getElementById("map"),
                });
                map.Event.bind("click", function () {
                    var mouseLocation = map.location(
                        longdo.LocationMode.Pointer
                    );
                    var location = addLocation();
                    addLocationToSheets(mouseLocation, location);
                });
                getSpreadsheet();
            }
            function getSpreadsheet() {
                var request = new XMLHttpRequest();
                request.open(
                    "GET",
                    "[YOUR-SCRIPT-URL]?action=getLocation",
                    true
                );

                request.onload = function () {
                    if (this.status >= 200 && this.status < 400) {
                        // Success!
                        var response = JSON.parse(this.response);
                        drawLocation(response);
                    } else {
                        // We reached our target server, but it returned an error
                    }
                };
                request.onerror = function () {
                    // There was a connection error of some sort
                };
                request.send();
            }
            function addLocationToSheets(mouseLocation, location) {
                var request = new XMLHttpRequest();
                request.open(
                    "POST",
                    "[YOUR-SCRIPT-URL]?action=addLocation",
                    true
                );
                request.send(
                    JSON.stringify({
                        depart: location.depart ?? "-",
                        sub_depart: location.sub_depart ?? "-",
                        name: location.name ?? "-",
                        address: location.address ?? "-",
                        lat: mouseLocation.lat,
                        lon: mouseLocation.lon,
                    })
                );
                request.onreadystatechange = () => {
                    if (request.readyState == 4) {
                        getSpreadsheet();
                    }
                };
            }
            function drawLocation(arr) {
                arr.forEach((location) => {
                    map.Overlays.add(
                        new longdo.Marker(
                            {
                                lon: Number(location.lon),
                                lat: Number(location.lat),
                            },
                            {
                                title: location.name,
                                detail: location.address,
                            }
                        )
                    );
                });
            }
            function addLocation() {
                let name = prompt("Please enter location name:");
                let address = prompt("Please enter location detail:");
                let depart = prompt("Please enter depart name:");
                let sub_depart = prompt("Please enter sub_depart detail:");
                return { name, address, depart, sub_depart };
            }
        </script>
    </head>

    <body onload="init();">
        <div id="map"></div>
    </body>
</html>

เป็นอันเสร็จสิ้นการเชื่อมและอัพเดทข้อมูลระหว่าง Google Spreadsheet และเว็บไซต์แสดงข้อมูลบนแผนที่เป็นที่เรียบร้อย


** อย่าลืมสมัครคีย์ฟรี และนำมาใส่ที่ [YOUR-KEY-API]

ดูเพิ่มเติม: คู่มือพัฒนาระบบ

ยังมีเทคนิคอีกมากมายที่จะให้นักพัฒนาทุกท่านได้ศึกษา สามารถเข้าร่วมกลุ่ม Longdo Map API Community กันได้ที่นี่เลยครับ : ) https://www.facebook.com/groups/708165893234850

พบกันในบทความถัดไปครับ