ตัวอย่างเว็บแอป Google Apps Script (โค้ดฝั่งเซิร์ฟเวอร์ + หน้า HTML/JS)
Code.gs— ฟังก์ชันdoGet()และsearchData(query)ที่อ่านข้อมูลจาก Google Sheet (sheet ชื่อData) แล้วค้นหาแบบไม่สนใจตัวพิมพ์index.html— หน้า UI สำหรับพิมพ์หรือกดไมค์ใช้เสียง (Web Speech API) เพื่อรับคำพูด แล้วส่งคำค้นไปยังsearchDataและแสดงผลเป็นตาราง
ขั้นตอนถัดไป (ทำเพียงครั้งเดียว):
- สร้างโปรเจ็กต์ Google Apps Script ใหม่ (https://script.google.com)
- เพิ่มไฟล์
Code.gsและindex.htmlแล้ววางโค้ดจาก canvas ลงไป (ผมรวมไว้เรียบร้อยใน canvas) - แก้ไข
Code.gs— เปลี่ยน'SPREADSHEET_ID'เป็น ID ของ Google Sheet ของคุณ (ตัวที่มีชีตชื่อData) - เตรียม Google Sheet: แถวแรกเป็น header (ชื่อคอลัมน์) ข้อมูลเริ่มแถวที่ 2 ขึ้นไป
- ติดตั้งสิทธิ์และ deploy: เลือก Deploy > New deployment > Web app ตั้งค่าให้
Execute asเป็นMeและWho has accessเป็นAnyone(หรือตามที่ต้องการ) - เปิด URL ที่ได้ จะเห็นหน้าเว็บที่มีช่องพิมพ์ ไอคอนไมโครโฟน และปุ่มค้นหา
ข้อจำกัด / หมายเหตุ:
- ฟีเจอร์เสียงใช้ Web Speech API — รองรับใน Chrome / Edge เดสก์ท็อปเป็นหลัก (บางเบราว์เซอร์/มือถืออาจไม่รองรับ)
- ถ้าต้องการให้รองรับภาษาอื่น แก้
recognition.langในindex.html(ตอนนี้ตั้งth-TH)
ด้านล่างนี้คือ โค้ดทั้งหมดแบบพร้อมใช้ สำหรับเว็บแอป Google Apps Script ค้นหาข้อมูลด้วย “เสียงหรือพิมพ์”
📁 ไฟล์ที่ 1: Code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('index')
.setTitle('ค้นหาข้อมูลด้วยเสียงหรือพิมพ์')
.setFaviconUrl('https://ssl.gstatic.com/docs/script/images/logo.png');
}
function searchData(query) {
try {
if (!query) return { success: true, results: [] };
query = String(query).trim().toLowerCase();
// 🔧 แก้ตรงนี้: ใส่ Spreadsheet ID ของคุณ
var ss = SpreadsheetApp.openById('YOUR_SPREADSHEET_ID_HERE');
var sh = ss.getSheetByName('Data'); // ชื่อชีตต้องตรงกับใน Spreadsheet
if (!sh) return { success: false, error: 'ไม่พบชีตชื่อ Data' };
var values = sh.getDataRange().getDisplayValues();
if (values.length <= 1) return { success: true, results: [] };
var headers = values[0];
var rows = values.slice(1);
var results = rows
.map((r, i) => ({
index: i + 2,
row: r,
joined: r.join(' ').toLowerCase()
}))
.filter(obj => obj.joined.includes(query))
.map(obj => ({ rowIndex: obj.index, values: obj.row }));
return { success: true, results, headers };
} catch (err) {
return { success: false, error: err.toString() };
}
}
📁 ไฟล์ที่ 2: index.html
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ค้นหาข้อมูลด้วยเสียงหรือพิมพ์</title>
<style>
body { font-family: "Prompt", Arial, sans-serif; margin: 20px; background: #f8fafc; }
.container { max-width: 800px; margin: 0 auto; background: white; padding: 20px; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
h2 { text-align: center; margin-bottom: 20px; }
.controls { display: flex; gap: 10px; }
input[type=text] { flex: 1; padding: 10px; border-radius: 8px; border: 1px solid #ccc; }
button { padding: 10px 15px; border: none; border-radius: 8px; cursor: pointer; font-weight: bold; }
#micBtn { background-color: #f1f5f9; }
#micBtn.mic-on { background-color: #ffe5e5; }
#searchBtn { background-color: #007bff; color: white; }
table { width: 100%; border-collapse: collapse; margin-top: 15px; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f1f1f1; }
.status { margin-top: 10px; font-size: 14px; color: #555; }
</style>
</head>
<body>
<div class="container">
<h2>🔍 ค้นหาข้อมูล (พูดหรือพิมพ์)</h2>
<div class="controls">
<input id="q" type="text" placeholder="พิมพ์หรือพูดคำค้น เช่น ชื่อ, หมายเลข, สถานที่...">
<button id="micBtn" title="พูดคำค้น">🎤</button>
<button id="searchBtn">ค้นหา</button>
</div>
<div class="status" id="status"></div>
<div id="results"></div>
</div>
<script>
const qInput = document.getElementById('q');
const micBtn = document.getElementById('micBtn');
const searchBtn = document.getElementById('searchBtn');
const statusDiv = document.getElementById('status');
const resultsDiv = document.getElementById('results');
let recognition;
let listening = false;
// ตรวจสอบว่ารองรับ SpeechRecognition หรือไม่
if (window.SpeechRecognition || window.webkitSpeechRecognition) {
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
recognition = new SpeechRecognition();
recognition.lang = 'th-TH';
recognition.interimResults = false;
recognition.onstart = () => {
listening = true;
micBtn.classList.add('mic-on');
statusDiv.textContent = '🎙️ กำลังฟัง...';
};
recognition.onend = () => {
listening = false;
micBtn.classList.remove('mic-on');
statusDiv.textContent = '';
};
recognition.onerror = (e) => {
listening = false;
micBtn.classList.remove('mic-on');
statusDiv.textContent = '⚠️ ข้อผิดพลาด: ' + e.error;
};
recognition.onresult = (evt) => {
const text = evt.results[0][0].transcript;
qInput.value = text;
statusDiv.textContent = 'ได้ข้อความ: ' + text;
doSearch();
};
} else {
micBtn.disabled = true;
micBtn.title = 'เบราว์เซอร์นี้ไม่รองรับคำสั่งเสียง';
}
micBtn.addEventListener('click', () => {
if (!recognition) return;
if (listening) recognition.stop();
else recognition.start();
});
searchBtn.addEventListener('click', doSearch);
qInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') doSearch(); });
function doSearch() {
const q = qInput.value.trim();
if (!q) {
statusDiv.textContent = '⚠️ กรุณาพิมพ์หรือพูดคำค้น';
return;
}
statusDiv.textContent = '🔎 กำลังค้นหา...';
resultsDiv.innerHTML = '';
google.script.run
.withSuccessHandler(renderResults)
.withFailureHandler((err) => statusDiv.textContent = '❌ เกิดข้อผิดพลาด: ' + err)
.searchData(q);
}
function renderResults(res) {
if (!res.success) {
statusDiv.textContent = '❌ ' + res.error;
return;
}
const count = res.results.length;
statusDiv.textContent = `พบ ${count} รายการ`;
if (!count) {
resultsDiv.innerHTML = '<p>ไม่พบข้อมูลที่ตรงกับคำค้น</p>';
return;
}
let html = '<table><thead><tr>';
html += res.headers.map(h => `<th>${escapeHtml(h)}</th>`).join('');
html += '<th>แถวที่</th></tr></thead><tbody>';
res.results.forEach(r => {
html += '<tr>' + r.values.map(c => `<td>${escapeHtml(c)}</td>`).join('') + `<td>${r.rowIndex}</td></tr>`;
});
html += '</tbody></table>';
resultsDiv.innerHTML = html;
}
function escapeHtml(s) {
if (s == null) return '';
return String(s)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>');
}
</script>
</body>
</html>
✅ วิธีใช้งาน
- เข้า https://script.google.com/
- สร้าง New Project
- สร้างไฟล์ 2 ไฟล์:
Code.gs→ วางโค้ดด้านบนindex.html→ วางโค้ด HTML ด้านบน
แก้ไขใน
Code.gs:var ss = SpreadsheetApp.openById('YOUR_SPREADSHEET_ID_HERE');ใส่ Spreadsheet ID ของคุณ (จาก URL ของ Google Sheet)- ใน Google Sheet ให้มีชีตชื่อ
Dataและมีหัวตาราง (เช่น ชื่อ, เบอร์, ที่อยู่ ฯลฯ) - ไปที่เมนู Deploy > New deployment > Web app
- Execute as: Me
- Who has access: Anyone
- แล้วกด Deploy
- เปิดลิงก์ที่ได้ → ทดลองพูดหรือพิมพ์คำค้นได้เลย 🎤🔎