Hướng dẫn

Hướng Dẫn Nhập Liệu Hàng Loạt Vào Google Sheets: Import CSV, Excel và API 2027

Tuân HoangTuân Hoang
27 tháng 2, 2026
Cập nhật: 6 tháng 10, 2026
14 phút đọc
Ảnh minh họa bài viết: Hướng Dẫn Nhập Liệu Hàng Loạt Vào Google Sheets: Import CSV, Excel và API 2027

Bạn đang mất nhiều giờ nhập tay từng dòng dữ liệu vào Google Sheets? Có cách nhanh hơn nhiều — import hàng loạt chỉ trong vài phút.

Hướng dẫn đầy đủ 2026: import CSV, Excel, dùng hàm IMPORTDATA, IMPORTRANGE, Google Sheets API, Apps Script — kèm xử lý trùng lặp, kiểm tra dữ liệu và tự động hóa lịch trình import.

Mục Lục

  1. Tại Sao Cần Import Dữ Liệu Hàng Loạt?
  2. Import File CSV/TSV Vào Google Sheets
  3. Import File Excel (.xlsx) Vào Google Sheets
  4. Hàm IMPORTDATA: Lấy Dữ Liệu Từ URL
  5. Hàm IMPORTRANGE: Kết Nối Nhiều Spreadsheet
  6. Hàm IMPORTHTML và IMPORTFEED
  7. Google Sheets API: Import Bằng Lập Trình
  8. Apps Script: Import Từ CSV, JSON, Database
  9. Xử Lý Trùng Lặp Và Kiểm Tra Dữ Liệu
  10. Chiến Lược Hợp Nhất (Merge) Dữ Liệu
  11. Import Từ Database: PostgreSQL, MySQL
  12. Google Forms: Import Tự Động Từ Khảo Sát
  13. Lịch Trình Tự Động Hóa Import Định Kỳ
  14. Use Cases Thực Tế Cho Doanh Nghiệp Việt Nam
  15. FAQ

1. Tại Sao Cần Import Dữ Liệu Hàng Loạt?

Nhập liệu thủ công là một trong những công việc tốn thời gian nhất mà các doanh nghiệp Việt Nam đang thực hiện mỗi ngày. Gõ tay từng dòng vừa chậm vừa dễ sai (gõ nhầm số, sót dòng, trùng dòng), và sai sót thường chỉ lộ ra khi đối chiếu cuối tháng. Import hàng loạt đưa dữ liệu vào nguyên khối từ file hoặc hệ thống gốc nên gần như loại bỏ lỗi gõ nhầm.

Các trường hợp cần import hàng loạt phổ biến nhất:

  • Chuyển hệ thống: Di chuyển dữ liệu từ phần mềm cũ (Excel, KiotViet, Sapo) sang Google Sheets hoặc phần mềm mới
  • Đồng bộ hàng ngày: Import đơn hàng từ sàn TMĐT (Shopee, Lazada) về Sheets tổng hợp
  • Báo cáo định kỳ: Import dữ liệu từ nhiều nguồn (ngân hàng, vận chuyển, CRM) để tổng hợp báo cáo
  • Dữ liệu sản phẩm: Cập nhật giá, tồn kho, mô tả sản phẩm cho hàng trăm/ngàn SKU
  • Dữ liệu khách hàng: Import danh sách khách hàng từ CRM, email marketing, form đăng ký

2. Import File CSV/TSV Vào Google Sheets

CSV (Comma-Separated Values) là định dạng phổ biến nhất để trao đổi dữ liệu giữa các hệ thống. Gần như mọi phần mềm quản lý đều có tính năng xuất CSV. Google Sheets hỗ trợ import CSV theo nhiều cách:

Cách 1: Upload Trực Tiếp (Giao Diện Web)

  1. Mở Google Sheets, click File trên menu
  2. Chon Import (hoặc "Nhập")
  3. Chọn tab Upload và kéo thả file CSV vào
  4. Cấu hình tùy chọn import:
    • Import location: Replace spreadsheet / Insert new sheet / Replace data at selected cell / Append to current sheet
    • Separator type: Detect automatically / Comma / Semicolon / Tab / Custom
    • Convert text to numbers, dates: Nên bật để Google tự động nhận diện kiểu dữ liệu
  5. Click Import data

Lưu ý quan trọng khi import CSV:

  • File CSV của Việt Nam thường dùng encoding UTF-8 hoặc ANSI. Nếu bị lỗi tiếng Việt, thử đổi encoding thành UTF-8-BOM
  • Dấu phân cách (separator) có thể là dấu phẩy (,) hoặc dấu chấm phẩy (;) tùy theo cấu hình hệ điều hành
  • Khi import "Append to current sheet", Google Sheets thêm vào cuối — không kiểm tra trùng lặp tự động
  • File CSV tối đa 5MB khi upload trực tiếp — file lớn hơn cần dùng API hoặc Apps Script

Cách 2: Import CSV Bằng Apps Script (Tự Động Hóa)

// Ham import CSV tu Google Drive vao Sheets
function importCSVFromDrive() {
  // Tim file CSV trong Google Drive theo ten
  const files = DriveApp.getFilesByName('don-hang-hom-nay.csv')

  if (!files.hasNext()) {
    Logger.log('Khong tim thay file CSV')
    return
  }

  const file = files.next()
  const csvContent = file.getBlob().getDataAsString('UTF-8')

  // Parse CSV thu cong (xu ly dau phay trong dau ngoac kep)
  const rows = parseCSV(csvContent)

  // Ghi vao sheet
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Don Hang')
  const lastRow = sheet.getLastRow()

  // Them tu dong vao cuoi (bo dong header - rows[0])
  if (rows.length > 1) {
    const dataRows = rows.slice(1) // Bo header
    sheet.getRange(lastRow + 1, 1, dataRows.length, dataRows[0].length)
         .setValues(dataRows)
    Logger.log('Da import ' + dataRows.length + ' dong')
  }
}

// Ham parse CSV xu ly dau phay trong dau ngoac kep
function parseCSV(csvText) {
  const rows = []
  const lines = csvText.split('
')

  for (const line of lines) {
    if (line.trim() === '') continue
    const row = []
    let current = ''
    let inQuotes = false

    for (let i = 0; i < line.length; i++) {
      const char = line[i]

      if (char === '"') {
        inQuotes = !inQuotes
      } else if (char === ',' && !inQuotes) {
        row.push(current.trim())
        current = ''
      } else {
        current += char
      }
    }
    row.push(current.trim())
    rows.push(row)
  }

  return rows
}

Cách 3: Import CSV Trực Tiếp Từ URL

Nếu file CSV của bạn được host trên URL công khai (ví dụ: S3, server riêng), bạn có thể import trực tiếp bằng hàm =IMPORTDATA() hoặc Apps Script:

// Import CSV tu URL bang Apps Script
function importCSVFromURL() {
  const csvUrl = 'https://example.com/exports/inventory-daily.csv'

  const response = UrlFetchApp.fetch(csvUrl, {
    headers: { 'Authorization': 'Bearer ' + getApiToken() }
  })

  const csvContent = response.getContentText('UTF-8')
  const rows = parseCSV(csvContent)

  const sheet = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName('Ton Kho')

  // Xoa du lieu cu truoc khi import moi
  const lastRow = sheet.getLastRow()
  if (lastRow > 1) {
    sheet.getRange(2, 1, lastRow - 1, sheet.getLastColumn()).clearContent()
  }

  // Ghi du lieu moi (bo header)
  if (rows.length > 1) {
    sheet.getRange(2, 1, rows.length - 1, rows[0].length)
         .setValues(rows.slice(1))
  }

  SpreadsheetApp.getActiveSpreadsheet().toast(
    'Import thanh cong ' + (rows.length - 1) + ' san pham',
    'Hoan thanh',
    5
  )
}

3. Import File Excel (.xlsx) Vào Google Sheets

Excel và Google Sheets có nhiều điểm tương đồng nhưng cũng có khác biệt quan trọng khi chuyển đổi. Đây là các cách import Excel hiệu quả:

Cách 1: Upload File .xlsx Trực Tiếp

Cách đơn giản nhất: kéo thả file .xlsx vào Google Drive. Google Drive tự động chuyển đổi sang Google Sheets. Hoặc trong Google Sheets, dùng File > Import > Upload và chọn file .xlsx.

Những thứ được và không được giữ khi chuyển đổi Excel sang Sheets:

Được giữ lại:

  • Dữ liệu, công thức cơ bản
  • Định dạng cell (màu, font, border)
  • Nhiều sheet
  • Named ranges
  • Charts cơ bản

Không được giữ:

  • VBA Macros
  • Một số hàm Excel đặc trưng
  • ActiveX controls
  • Một số pivot table phức tạp
  • Slicers

Cách 2: Dùng Apps Script Import Excel Từ Drive

// Chuyen doi va import file Excel tu Drive
function importExcelFromDrive(excelFileName) {
  // Tim file Excel trong Drive
  const files = DriveApp.getFilesByName(excelFileName || 'bao-cao.xlsx')
  if (!files.hasNext()) {
    throw new Error('Khong tim thay file: ' + excelFileName)
  }

  const excelFile = files.next()

  // Chuyen doi sang Google Sheets tam thoi
  const tempSheets = Drive.Files.copy(
    { title: 'temp_import_' + Date.now(), mimeType: 'application/vnd.google-apps.spreadsheet' },
    excelFile.getId()
  )

  const tempSpreadsheet = SpreadsheetApp.openById(tempSheets.id)
  const sourceSheet = tempSpreadsheet.getSheets()[0]
  const sourceData = sourceSheet.getDataRange().getValues()

  // Copy du lieu sang sheet dich
  const targetSheet = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName('Du Lieu Import') ||
    SpreadsheetApp.getActiveSpreadsheet().insertSheet('Du Lieu Import')

  targetSheet.clearContents()
  if (sourceData.length > 0) {
    targetSheet.getRange(1, 1, sourceData.length, sourceData[0].length)
               .setValues(sourceData)
  }

  // Xoa file tam
  DriveApp.getFileById(tempSheets.id).setTrashed(true)

  Logger.log('Da import ' + sourceData.length + ' dong tu ' + excelFileName)
  return sourceData.length
}

4. Hàm IMPORTDATA: Lấy Dữ Liệu Từ URL

Ham =IMPORTDATA(url) là cách đơn giản nhất để import dữ liệu CSV hoặc TSV từ một URL công khai vào Google Sheets. Hàm này tự động làm mới dữ liệu mỗi khi bạn mở spreadsheet.

Cú Pháp Và Ví Dụ

// Cu phap co ban
=IMPORTDATA("https://example.com/data.csv")

// Import du lieu ty gia ngoai te tu API cong khai
=IMPORTDATA("https://open.er-api.com/v6/latest/USD")

// Import du lieu thoi tiet (neu API tra CSV)
=IMPORTDATA("https://api.weather.com/data?format=csv&city=hanoi")

// Import voi encoding parameter (mot so URL ho tro)
=IMPORTDATA("https://example.com/data.csv?encoding=utf8")

Giới hạn của IMPORTDATA:

  • Chỉ làm việc với URL công khai (không cần authentication)
  • Dữ liệu tự động làm mới — không thể lịch trình giờ cụ thể
  • Giới hạn 1000 dòng dữ liệu
  • Chậm hơn so với import trực tiếp
  • Không xử lý được JSON (chỉ CSV/TSV)

Trường Hợp Thực Tế: Import Giá Vàng Từ API

// Import gia vang SJC tu nguon cong khai
// (dat o cell A1 cua sheet "Gia Vang")
=IMPORTDATA("https://sjc.com.vn/GoldPrice/Index.aspx?format=csv")

// Import ty gia tu NHNN
=IMPORTDATA("https://www.vietcombank.com.vn/api/exchangerates?format=csv")

// Ket hop voi ham de xu ly du lieu
=INDEX(IMPORTDATA("https://example.com/prices.csv"),2,3)
// Lay gia tri o dong 2, cot 3 cua CSV

5. Hàm IMPORTRANGE: Kết Nối Nhiều Spreadsheet

Ham =IMPORTRANGE() cho phép lấy dữ liệu từ một Google Sheets khác vào spreadsheet hiện tại. Đây là tính năng rất mạnh để tạo báo cáo tổng hợp từ nhiều nguồn.

Cú Pháp

// Cu phap co ban
=IMPORTRANGE("spreadsheet_id_hoac_url", "sheet_name!range")

// Vi du 1: Import toan bo du lieu tu Sheet1
=IMPORTRANGE("1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms", "Sheet1!A:Z")

// Vi du 2: Import vung cu the
=IMPORTRANGE("1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms", "Don Hang!A2:F1000")

// Vi du 3: Import voi URL day du
=IMPORTRANGE("https://docs.google.com/spreadsheets/d/1BxiMVs0.../edit", "Ton Kho!A:E")

// Ket hop voi QUERY de loc du lieu truoc khi import
=QUERY(IMPORTRANGE("spreadsheet_id", "Sheet1!A:F"),
       "SELECT Col1, Col2, Col4 WHERE Col3 = 'Ha Noi'")

Use Case: Báo Cáo Tổng Hợp Từ Nhiều Cửa Hàng

Một doanh nghiệp có 3 cửa hàng, mỗi cửa hàng dùng 1 Google Sheets riêng. Để tạo báo cáo tổng hợp, tạo thêm 1 spreadsheet "Dashboard" và dùng IMPORTRANGE:

// Sheet "Dashboard Tong Hop" - lay doanh thu 3 cua hang
// Cot A: Ma don hang, Cot B: Doanh thu, Cot C: Cua hang

// Cua hang 1
=IMPORTRANGE("id_cua_hang_1", "Doanh Thu!A2:C")

// Cua hang 2 - dat o dong tiep theo sau cua hang 1
// Dung OFFSET hoac QUERY de sap xep dong

// Gop 3 cua hang bang QUERY + IMPORTRANGE
=QUERY({
  IMPORTRANGE("id_cua_hang_1", "Doanh Thu!A2:C");
  IMPORTRANGE("id_cua_hang_2", "Doanh Thu!A2:C");
  IMPORTRANGE("id_cua_hang_3", "Doanh Thu!A2:C")
}, "SELECT * ORDER BY Col2 DESC")

Lưu ý khi dùng IMPORTRANGE:

  • Lần đầu dùng, cần cấp quyền truy cập bằng cách click "Allow access"
  • Người tạo hàm chỉ cần quyền xem (Viewer) trên spreadsheet nguồn
  • Dữ liệu cập nhật theo thời gian thực khi spreadsheet nguồn thay đổi
  • Nhiều IMPORTRANGE trong cùng một file có thể làm chậm spreadsheet
  • Nên gom dữ liệu bằng ít hàm IMPORTRANGE lấy cả vùng lớn thay vì hàng trăm hàm lấy từng ô

6. Hàm IMPORTHTML và IMPORTFEED

Ngoài IMPORTDATA và IMPORTRANGE, Google Sheets còn có hai hàm import mạnh khác:

IMPORTHTML — Lấy Dữ Liệu Từ Bảng HTML Trên Web

// Cu phap: =IMPORTHTML(url, query, index)
// query: "table" hoac "list"
// index: vi tri cua bang thu may (bat dau tu 1)

// Import bang ty gia ngoai te tu website ngan hang
=IMPORTHTML("https://www.vietcombank.com.vn/exchangerates", "table", 1)

// Import danh sach (ul/ol) tu trang web
=IMPORTHTML("https://example.com/products", "list", 2)

// Ket hop voi ham de lay du lieu cu the
=INDEX(IMPORTHTML("https://tygia.com/ngoai-te", "table", 1), 3, 2)
// Lay gia tri dong 3, cot 2 tu bang dau tien

IMPORTFEED — Import RSS/Atom Feed

// Import tin tuc tu RSS feed
=IMPORTFEED("https://vnexpress.net/rss/kinh-doanh.rss", "items", TRUE, 10)
// Tham so: url, query, headers, num_items

// Lay chi tieu de cua tin tuc gan nhat
=IMPORTFEED("https://cafef.vn/thi-truong-chung-khoan.rss", "items title", FALSE, 20)

// Lay URL cua tin tuc
=IMPORTFEED("https://cafef.vn/thi-truong-chung-khoan.rss", "items url", FALSE, 10)

7. Google Sheets API: Import Bằng Lập Trình

Khi cần import dữ liệu từ ứng dụng khác vào Google Sheets theo chương trình, Google Sheets API v4 là công cụ chính. API này cho phép đọc, ghi, cập nhật dữ liệu bất kỳ lúc nào.

Thiết Lập Google Sheets API

  1. Vao Google Cloud Console (console.cloud.google.com)
  2. Tạo project mới hoặc chọn project hiện tại
  3. Kích hoạt Google Sheets API va Google Drive API
  4. Tao Service Account (cho server-to-server) hoac OAuth 2.0 (cho ứng dụng người dùng)
  5. Chia sẻ Google Sheets với email của Service Account

Import Dữ Liệu Bằng Node.js

// Cai dat: npm install googleapis
import { google } from 'googleapis'
import { JWT } from 'google-auth-library'

// Xac thuc bang Service Account
const auth = new JWT({
  email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
  key: process.env.GOOGLE_PRIVATE_KEY?.replace(/\n/g, '
'),
  scopes: ['https://www.googleapis.com/auth/spreadsheets'],
})

const sheets = google.sheets({ version: 'v4', auth })

// Ham append du lieu vao sheets (them vao cuoi)
async function appendDataToSheet(
  spreadsheetId: string,
  sheetName: string,
  data: any[][]
) {
  const range = sheetName + '!A:Z'

  await sheets.spreadsheets.values.append({
    spreadsheetId,
    range,
    valueInputOption: 'USER_ENTERED', // Nhan dien cong thuc va dinh dang
    insertDataOption: 'INSERT_ROWS',
    requestBody: {
      values: data,
    },
  })

  console.log('Da append ' + data.length + ' dong vao ' + sheetName)
}

// Ham ghi de du lieu (replace)
async function writeDataToSheet(
  spreadsheetId: string,
  sheetName: string,
  data: any[][],
  startRow: number = 1
) {
  const range = sheetName + '!A' + startRow

  await sheets.spreadsheets.values.update({
    spreadsheetId,
    range,
    valueInputOption: 'USER_ENTERED',
    requestBody: {
      values: data,
    },
  })
}

// Su dung
const SPREADSHEET_ID = '1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms'

// Import don hang tu database vao Sheets
const orders = await db.orders.findMany({
  where: { createdAt: { gte: startOfDay } },
  orderBy: { createdAt: 'desc' }
})

const rows = orders.map(o => [
  o.id, o.customerName, o.total, o.status,
  o.createdAt.toLocaleDateString('vi-VN')
])

await appendDataToSheet(SPREADSHEET_ID, 'Don Hang', rows)

Batch Update — Import Nhiều Vùng Cùng Lúc

// Batch update: cap nhat nhieu vung trong 1 API call
// Hieu qua hon khi can update nhieu sheet cung luc
async function batchUpdateSheets(
  spreadsheetId: string,
  updates: Array<{ range: string; values: any[][] }>
) {
  const data = updates.map(u => ({
    range: u.range,
    values: u.values,
  }))

  await sheets.spreadsheets.values.batchUpdate({
    spreadsheetId,
    requestBody: {
      valueInputOption: 'USER_ENTERED',
      data,
    },
  })

  console.log('Batch update ' + updates.length + ' vung thanh cong')
}

// Vi du su dung batch update
await batchUpdateSheets(SPREADSHEET_ID, [
  { range: 'Ton Kho!A2:C500', values: inventoryData },
  { range: 'Doanh Thu!A2:E100', values: revenueData },
  { range: 'Khach Hang!A2:G200', values: customerData },
])

8. Apps Script: Import Tu CSV, JSON, Database

Google Apps Script chạy trực tiếp trong Google Sheets, không cần server riêng. Đây là công cụ mạnh nhất để tự động hóa import dữ liệu định kỳ.

Import Dữ Liệu JSON Từ API

// Import don hang tu API JSON
function importOrdersFromAPI() {
  const apiUrl = 'https://api.myshop.com/orders'
  const apiKey = PropertiesService.getScriptProperties().getProperty('API_KEY')

  // Lay don hang trong 24h qua
  const yesterday = new Date()
  yesterday.setDate(yesterday.getDate() - 1)
  const isoDate = yesterday.toISOString()

  const response = UrlFetchApp.fetch(
    apiUrl + '?since=' + isoDate + '&limit=500',
    {
      headers: {
        'Authorization': 'Bearer ' + apiKey,
        'Content-Type': 'application/json'
      },
      muteHttpExceptions: true
    }
  )

  if (response.getResponseCode() !== 200) {
    Logger.log('Loi API: ' + response.getContentText())
    return
  }

  const data = JSON.parse(response.getContentText())
  const orders = data.orders || data.data || data

  if (!orders || orders.length === 0) {
    Logger.log('Khong co don hang moi')
    return
  }

  // Chuyen JSON sang mang 2 chieu
  const rows = orders.map(order => [
    order.id,
    order.customer_name,
    order.customer_phone,
    order.total_amount,
    order.status,
    order.items?.length || 0,
    new Date(order.created_at).toLocaleDateString('vi-VN'),
    order.payment_method
  ])

  const sheet = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName('Don Hang API') ||
    SpreadsheetApp.getActiveSpreadsheet().insertSheet('Don Hang API')

  // Them header neu sheet trong
  if (sheet.getLastRow() === 0) {
    sheet.appendRow(['Ma Don', 'Khach Hang', 'SDT', 'Tong Tien', 'Trang Thai',
                     'So SP', 'Ngay Dat', 'Thanh Toan'])
  }

  // Append du lieu moi
  rows.forEach(row => sheet.appendRow(row))

  Logger.log('Da import ' + rows.length + ' don hang moi')
  SpreadsheetApp.getActiveSpreadsheet().toast(
    'Import ' + rows.length + ' don hang thanh cong!', 'API Import', 5
  )
}

Import Từ Google Form Responses

// Xu ly du lieu khi co submission tu Google Form
// Gan trigger onFormSubmit trong Form editor

function onFormSubmit(e) {
  const responses = e.values // Mang gia tri cac cau tra loi
  const timestamp = responses[0] // Cot dau tien luon la timestamp

  // Lay sheet xu ly don hang
  const sheet = SpreadsheetApp.openById('SPREADSHEET_ID')
    .getSheetByName('Xu Ly')

  // Xu ly va chuyen dinh dang truoc khi luu
  const processedRow = [
    timestamp,
    responses[1], // Ho ten
    responses[2], // SDT
    responses[3], // San pham
    parseInt(responses[4]) || 1, // So luong (default 1)
    parseFloat(responses[5]?.replace(/[.,]/g, '')) || 0, // Gia
    'Moi', // Trang thai mac dinh
    generateOrderId() // Tao ma don tu dong
  ]

  sheet.appendRow(processedRow)

  // Gui email xac nhan cho khach
  GmailApp.sendEmail(
    responses[6], // Email khach hang
    'Xac nhan don hang #' + processedRow[7],
    'Cam on ban da dat hang! Ma don cua ban: ' + processedRow[7]
  )
}

function generateOrderId() {
  const date = new Date()
  const prefix = 'DH'
  const dateStr = date.getFullYear().toString().slice(-2) +
    String(date.getMonth() + 1).padStart(2, '0') +
    String(date.getDate()).padStart(2, '0')
  const random = Math.floor(Math.random() * 9000 + 1000)
  return prefix + dateStr + random
}

9. Xử Lý Trùng Lặp Và Kiểm Tra Dữ Liệu Sau Import

Một trong những vấn đề lớn nhất khi import dữ liệu là trùng lặp. Nếu bạn import mỗi ngày, các đơn hàng cũ có thể bị import nhiều lần. Đây là các cách xử lý:

Cách 1: Kiểm Tra Trùng Lặp Bằng Hàm Sheets

// Them cot "Trung lap" ben canh du lieu import
// Cot A: Ma don hang, kiem tra trong cot A cua sheet chinh

// Cong thuc kiem tra trung lap (dat o cot kiem tra)
=COUNTIF('Du Lieu Chinh'!$A:$A, A2) > 1

// Loc ra cac dong khong trung lap
=FILTER(A2:F100, COUNTIF(A2:A100, A2:A100) = 1)

// Dung UNIQUE de loai bo trung lap
=UNIQUE(A2:F100)

// Dem so ban ghi trung lap
=SUMPRODUCT((COUNTIF(A2:A100,A2:A100)>1)*1)

Cách 2: Xử Lý Trùng Lặp Bằng Apps Script

// Loai bo trung lap truoc khi append du lieu moi
function appendWithDeduplicate(
  sheet,
  newData,
  keyColumnIndex = 0 // Chi so cot khoa chinh (0 = cot A)
) {
  // Lay tat ca gia tri hien co cua cot khoa chinh
  const lastRow = sheet.getLastRow()
  const existingKeys = new Set()

  if (lastRow > 1) {
    const existingData = sheet.getRange(2, keyColumnIndex + 1, lastRow - 1, 1)
                              .getValues()
    existingData.forEach(row => existingKeys.add(String(row[0])))
  }

  // Loc ra cac dong chua ton tai
  const uniqueRows = newData.filter(row => {
    const key = String(row[keyColumnIndex])
    if (existingKeys.has(key)) return false
    existingKeys.add(key) // Them vao set de tranh trung lap trong batch moi
    return true
  })

  if (uniqueRows.length === 0) {
    Logger.log('Khong co du lieu moi (tat ca da ton tai)')
    return 0
  }

  // Append cac dong unique
  sheet.getRange(sheet.getLastRow() + 1, 1, uniqueRows.length, uniqueRows[0].length)
       .setValues(uniqueRows)

  Logger.log('Da them ' + uniqueRows.length + ' dong moi, bo qua ' +
    (newData.length - uniqueRows.length) + ' ban ghi trung lap')
  return uniqueRows.length
}

Kiểm Tra Chất Lượng Dữ Liệu Sau Import

// Kiem tra toan ven du lieu sau import
function validateImportedData(sheet) {
  const data = sheet.getDataRange().getValues()
  const headers = data[0]
  const errors = []

  for (let i = 1; i < data.length; i++) {
    const row = data[i]
    const rowNum = i + 1

    // Kiem tra truong bat buoc
    if (!row[0] || row[0] === '') {
      errors.push('Dong ' + rowNum + ': Thieu ma don hang')
    }

    // Kiem tra so tien hop le
    if (isNaN(row[3]) || row[3] < 0) {
      errors.push('Dong ' + rowNum + ': So tien khong hop le (' + row[3] + ')')
    }

    // Kiem tra dinh dang ngay
    if (row[6] && !(row[6] instanceof Date) && isNaN(Date.parse(row[6]))) {
      errors.push('Dong ' + rowNum + ': Ngay khong hop le (' + row[6] + ')')
    }

    // Kiem tra so dien thoai (Viet Nam)
    if (row[2] && !/^(0[3-9]d{8}|(+84)[3-9]d{8})$/.test(row[2])) {
      errors.push('Dong ' + rowNum + ': SDT khong dung dinh dang (' + row[2] + ')')
    }
  }

  if (errors.length > 0) {
    Logger.log('Phat hien ' + errors.length + ' loi:')
    errors.forEach(e => Logger.log('  - ' + e))
  } else {
    Logger.log('Tat ca du lieu hop le!')
  }

  return errors
}

10. Chiến Lược Hợp Nhất (Merge) Dữ Liệu

Khi import dữ liệu mới, đôi khi bạn muốn cập nhật record hiện có thay vì tạo mới. Đây là các chiến lược merge phổ biến:

Chiến lược Mô tả Dùng khi
Insert Only Chỉ thêm mới, bỏ qua trùng lặp Log, lịch sử giao dịch
Upsert Thêm mới nếu chưa có, cập nhật nếu đã có Tồn kho, thông tin sản phẩm
Replace All Xóa hết và ghi lại toàn bộ Báo cáo cuối ngày, snapshot
Append Only Luôn thêm mới, kể cả trùng lặp Raw data, audit log
Merge Fields Chỉ cập nhật một số cột cụ thể Cập nhật trạng thái, giá
// Upsert: them moi neu chua co, cap nhat neu da co
function upsertData(sheet, newData, keyColumnIndex = 0) {
  const lastRow = sheet.getLastRow()
  const headerRow = 1

  // Tao map: key -> so dong
  const keyToRowMap = {}
  if (lastRow > headerRow) {
    const existingKeys = sheet.getRange(
      headerRow + 1, keyColumnIndex + 1,
      lastRow - headerRow, 1
    ).getValues()

    existingKeys.forEach((row, idx) => {
      keyToRowMap[String(row[0])] = idx + headerRow + 1
    })
  }

  const rowsToInsert = []

  for (const newRow of newData) {
    const key = String(newRow[keyColumnIndex])

    if (keyToRowMap[key]) {
      // Cap nhat dong hien co
      const targetRow = keyToRowMap[key]
      sheet.getRange(targetRow, 1, 1, newRow.length).setValues([newRow])
    } else {
      // Them vao danh sach insert
      rowsToInsert.push(newRow)
      keyToRowMap[key] = lastRow + rowsToInsert.length // Cap nhat map
    }
  }

  // Batch insert cac dong moi
  if (rowsToInsert.length > 0) {
    sheet.getRange(
      sheet.getLastRow() + 1, 1,
      rowsToInsert.length, rowsToInsert[0].length
    ).setValues(rowsToInsert)
  }

  Logger.log('Upsert: cap nhat ' + (newData.length - rowsToInsert.length) +
    ', them moi ' + rowsToInsert.length)
}

11. Import Từ Database: PostgreSQL, MySQL

Nhiều doanh nghiệp muốn đồng bộ dữ liệu từ database của họ sang Google Sheets để báo cáo. Cách phổ biến nhất là dùng Apps Script với JDBC connection hoặc qua API trung gian.

Cách 1: Dùng Apps Script JDBC (Cloud SQL)

// Ket noi toi Cloud SQL (PostgreSQL) tu Apps Script
function importFromCloudSQL() {
  // Apps Script ho tro JDBC cho Cloud SQL, MySQL, Oracle, SQL Server
  const conn = Jdbc.getCloudSqlConnection(
    'jdbc:google:mysql://project-id:region:instance-name/dbname',
    'username',
    PropertiesService.getScriptProperties().getProperty('DB_PASSWORD')
  )

  const stmt = conn.createStatement()
  const results = stmt.executeQuery(
    "SELECT id, customer_name, total, created_at " +
    "FROM orders " +
    "WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY) " +
    "ORDER BY created_at DESC"
  )

  const sheet = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName('Du Lieu DB')

  sheet.clearContents()
  sheet.appendRow(['Ma Don', 'Khach Hang', 'Tong Tien', 'Ngay Dat'])

  while (results.next()) {
    sheet.appendRow([
      results.getInt(1),
      results.getString(2),
      results.getDouble(3),
      results.getTimestamp(4)
    ])
  }

  results.close()
  stmt.close()
  conn.close()
  Logger.log('Import tu Cloud SQL thanh cong')
}

Cách 2: Qua API Trung Gian (Recommended)

Thay vì kết nối trực tiếp từ Apps Script, cách an toàn hơn là tạo một API endpoint riêng trong ứng dụng của bạn:

// API endpoint trong ung dung Node.js cua ban
// GET /api/export/orders?since=2026-01-01&format=json

// Trong Apps Script, goi API nay
function importFromCustomAPI() {
  const apiBase = 'https://your-app.com/api'
  const apiKey = PropertiesService.getScriptProperties().getProperty('API_KEY')

  const yesterday = new Date()
  yesterday.setDate(yesterday.getDate() - 1)
  const since = yesterday.toISOString().split('T')[0]

  const response = UrlFetchApp.fetch(
    apiBase + '/export/orders?since=' + since + '&format=json',
    { headers: { 'X-API-Key': apiKey } }
  )

  const { orders } = JSON.parse(response.getContentText())

  const sheet = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName('Bao Cao Ngay')

  const rows = orders.map(o => [
    o.id, o.customer_name, o.total,
    o.status, new Date(o.created_at)
  ])

  appendWithDeduplicate(sheet, rows, 0)
}

12. Google Forms: Import Tự Động Từ Khảo Sát

Google Forms tự động lưu kết quả khảo sát vào một Google Sheets liên kết. Nhưng đôi khi bạn cần xử lý thêm trước khi dữ liệu có ích:

// Trigger chay moi khi co form submission moi
function setupFormTrigger() {
  const form = FormApp.openById('FORM_ID')
  ScriptApp.newTrigger('processFormSubmission')
    .forForm(form)
    .onFormSubmit()
    .create()
}

// Xu ly va chuyen form response sang sheet xu ly
function processFormSubmission(e) {
  const formResponse = e.response
  const itemResponses = formResponse.getItemResponses()

  // Trich xuat cac truong cu the
  const data = {
    timestamp: formResponse.getTimestamp(),
    fullName: itemResponses[0]?.getResponse(),
    phone: itemResponses[1]?.getResponse(),
    product: itemResponses[2]?.getResponse(),
    quantity: parseInt(itemResponses[3]?.getResponse()) || 1,
    address: itemResponses[4]?.getResponse(),
    note: itemResponses[5]?.getResponse() || '',
  }

  // Ghi vao sheet xu ly voi dinh dang chuan hoa
  const targetSheet = SpreadsheetApp.openById('SPREADSHEET_ID')
    .getSheetByName('Don Hang Forms')

  targetSheet.appendRow([
    data.timestamp,
    data.fullName?.trim(),
    data.phone?.trim().replace(/s+/g, ''),
    data.product,
    data.quantity,
    data.address?.trim(),
    data.note,
    'Moi', // Trang thai
    generateOrderId()
  ])

  // Gui thong bao Telegram cho chu shop
  sendTelegramNotification(
    'Don hang moi tu Form:
' +
    data.fullName + ' - ' + data.phone + '
' +
    data.product + ' x' + data.quantity
  )
}

13. Lịch Trình Tự Động Hóa Import Định Kỳ

Sau khi đã viết hàm import, bước tiếp theo là lịch trình chạy tự động. Apps Script hỗ trợ time-based triggers:

// Thiet lap tat ca triggers can thiet
function setupAllTriggers() {
  // Xoa triggers cu truoc
  ScriptApp.getProjectTriggers().forEach(t => ScriptApp.deleteTrigger(t))

  // Import don hang moi moi gio
  ScriptApp.newTrigger('importOrdersFromAPI')
    .timeBased()
    .everyHours(1)
    .create()

  // Import ton kho moi 30 phut
  ScriptApp.newTrigger('importInventoryFromAPI')
    .timeBased()
    .everyMinutes(30)
    .create()

  // Bao cao tong ket moi ngay luc 23:00
  ScriptApp.newTrigger('generateDailyReport')
    .timeBased()
    .everyDays(1)
    .atHour(23)
    .create()

  // Import tu file CSV moi sang thu (du lieu tuan)
  ScriptApp.newTrigger('importWeeklyCSV')
    .timeBased()
    .onWeekDay(ScriptApp.WeekDay.MONDAY)
    .atHour(7)
    .create()

  Logger.log('Da thiet lap 4 triggers tu dong')
}

// Ham kiem tra trang thai import (chay hang ngay)
function checkImportHealth() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName('Import Log')

  if (!sheet) return

  const lastRow = sheet.getLastRow()
  if (lastRow < 2) return

  const lastImport = sheet.getRange(lastRow, 1).getValue()
  const now = new Date()
  const hoursSinceLastImport = (now - lastImport) / (1000 * 60 * 60)

  if (hoursSinceLastImport > 3) {
    // Canh bao neu qua 3 gio khong co import
    sendTelegramNotification(
      'CANH BAO: Import du lieu bi gian doan! ' +
      Math.round(hoursSinceLastImport) + ' gio khong co du lieu moi.'
    )
  }
}

14. Use Cases Thực Tế Cho Doanh Nghiệp Việt Nam

Use Case 1: Cửa Hàng Bán Lẻ — Import Đơn Hàng Shopee/Lazada

Quy trình phổ biến: Shopee/Lazada xuất file CSV đơn hàng -> import vào Google Sheets hàng ngày -> tổng hợp báo cáo doanh thu.

Buoc Công việc Công cụ
1 Xuất CSV từ Shopee Seller Center (lịch trình auto download) Shopee API / thủ công
2 Import CSV vào Google Sheets (tự động mỗi sáng) Apps Script + Drive
3 Loại bỏ trùng lặp, kiểm tra dữ liệu Apps Script upsert
4 IMPORTRANGE vào sheet báo cáo tổng hợp Hàm IMPORTRANGE
5 Dashboard tự động cập nhật số liệu QUERY + Charts

Use Case 2: Công Ty Dịch Vụ — Import Lịch Làm Việc Nhân Viên

HR dùng Google Forms để nhân viên đăng ký lịch. Apps Script tự động xử lý và tổng hợp vào Sheets lương/timesheet.

Use Case 3: Nhà Hàng/F&B — Import Dữ Liệu POS Cuối Ngày

Hệ thống POS xuất file CSV cuối ngày. Apps Script tự động import, tính tổng doanh thu theo món, theo ca làm việc, gửi báo cáo cho chủ nhà hàng qua Telegram.

FAQ — Câu Hỏi Thường Gặp

Google Sheets có import được file CSV lớn không (>10MB)?

File lớn hơn 5MB không thể upload trực tiếp qua giao diện. Giải pháp: chia file thành nhiều phần nhỏ, hoặc dùng Apps Script với UrlFetchApp (hỗ trợ file lớn hơn) hoặc Sheets API (không giới hạn file size thực tế, giới hạn theo số ô của file: tối đa 10 triệu ô).

Làm sao giữ định dạng khi import CSV tiếng Việt?

Đảm bảo file CSV lưu ở encoding UTF-8. Trong Excel, khi lưu CSV hãy chọn "CSV UTF-8 (Comma delimited)". Khi import vào Sheets, chọn "Detect automatically" cho separator và tắt "Convert text to numbers" nếu bạn muốn giữ nguyên văn bản.

IMPORTRANGE bị lỗi "You don't have permission" phải làm gì?

Người dùng đang xem spreadsheet chưa cấp quyền truy cập spreadsheet nguồn. Click vào cell có hàm IMPORTRANGE, sẽ xuất hiện nút "Allow access". Click vào đó để cấp quyền. Quyền này gắn với tài khoản Google của người dùng.

Apps Script trigger có chạy được khi không mở Sheets không?

Có. Time-based triggers chạy trên server của Google, hoàn toàn tự động dù bạn có mở spreadsheet hay không. Tuy nhiên, mỗi lần chạy script tối đa 6 phút (cả tài khoản miễn phí lẫn Workspace). Nếu import lớn, hãy chia thành nhiều batch nhỏ.

SheetStore có hỗ trợ import hàng loạt không?

Các phần mềm của SheetStore chạy trên Google Sheets, nên bạn dùng được tất cả các kỹ thuật trên để đưa dữ liệu cũ vào. Xem các phần mềm để hiểu rõ hơn.

Xem Các Phần Mềm Google Sheets Của SheetStore

Mỗi phần mềm có trang chi tiết với tính năng, giá và demo để bạn xem trước khi mua.

Xem Danh Sách Phần Mềm

Chia sẻ bài viết:

Tuân Hoang

Tuân Hoang

Đội ngũ SheetStore

Google SheetsGoogle Apps ScriptCRMAutomationPhần mềm quản lý doanh nghiệp

Google Workspace Certified, 5+ years experience

Bạn thấy bài viết hữu ích?

Đăng ký nhận thông báo khi có bài viết mới.

Nhận thông báo khi có bài viết mới. Không spam, hứa luôn! 😊

Bình luận (0)

Vui lòng đăng nhập để tham gia thảo luận