Inforact Docs
Base

Công thức (Formula)

Tính toán tự động trong một cột bằng công thức — tham chiếu cột khác, dùng hàm có sẵn, và lồng nhiều hàm vào nhau cho các quy tắc phức tạp hơn.

Formula là một kiểu cột tính toán: thay vì nhập tay, giá trị của cột được Base tự tính từ một công thức bạn viết, tham chiếu tới các cột khác trong cùng bảng (và có thể cả bảng khác). Công thức chạy lại mỗi khi dữ liệu đầu vào đổi — bạn không cần cập nhật tay.

Mở dialog soạn công thức

Khi thêm cột mới (hoặc sửa một cột Formula có sẵn), chọn kiểu Formula trong danh sách kiểu dữ liệu — dialog Chỉnh sửa công thức mở ra.

Dialog chia 3 vùng: bên trái là danh sách cột trong bảng và các hàm có sẵn (bấm để chèn nhanh vào công thức); giữa là ô soạn công thức cùng bảng xem trước kết quả tính trên chính bản ghi thật của bảng; bên phải là mô tả + ví dụ của hàm bạn đang gõ hoặc đang rê chuột tới.

Dialog Chỉnh sửa công thức với 3 vùng: cột & hàm, editor + xem trước, mô tả hàm
Dialog soạn công thức — gõ công thức ở giữa, xem ngay kết quả tính trên dữ liệu thật bên dưới.

Cách dùng cơ bản

  • Tham chiếu một cột bằng cách bọc tên cột trong dấu ngoặc nhọn, ví dụ {Số lượng}. Gõ dấu { để Base gợi ý danh sách cột.
  • Gõ tên hàm (vd IF, SUM) để chèn nhanh — con trỏ sẽ đặt sẵn giữa hai dấu ngoặc để bạn gõ tiếp tham số.
  • Khu vực "Xem trước trên bản ghi thật" luôn tính công thức trên vài bản ghi thật của bảng — không phải dữ liệu mẫu giả định — để bạn biết ngay công thức có đúng ý trước khi lưu.
  • Khi công thức còn sai cú pháp hoặc sai kiểu tham số, dialog báo lỗi ngay kèm gợi ý sửa (nếu có), và nút Lưu công thức bị khoá cho tới khi công thức hợp lệ.

Kiểu dữ liệu trả về

Base tự suy ra kiểu dữ liệu của cột Formula từ chính công thức (Văn bản, Số, Đúng/Sai, Ngày hoặc Ngày giờ) — hiển thị ngay cạnh dòng "Công thức hợp lệ" ở chân dialog. Với IF/SWITCH, nếu các nhánh trả về kiểu khác nhau (ví dụ một nhánh trả số, nhánh kia trả chữ), Base sẽ hợp nhất theo kiểu chung gần nhất (thường là Văn bản).

Bảng tra cứu đầy đủ các hàm

Logic

HàmCú phápMô tảVí dụKết quả
IFIF(điều_kiện, nếu_đúng, nếu_sai)Trả về giá trị đầu nếu điều kiện đúng, ngược lại trả giá trị sau.IF({Số lượng} > 10, "Sỉ", "Lẻ")"Sỉ"
SWITCHSWITCH(biểu_thức, khớp1, giá_trị1, …, mặc_định)Chọn kết quả theo giá trị khớp; không khớp thì lấy mặc định.SWITCH({Cấp}, 1, "Vàng", 2, "Bạc", "Đồng")"Bạc"
ANDAND(a, b, …)Đúng khi TẤT CẢ điều kiện đúng.AND({Tuổi} >= 18, {Đã duyệt})true
OROR(a, b, …)Đúng khi CÓ ÍT NHẤT một điều kiện đúng.OR({Vip}, {Tổng} > 1000000)true
NOTNOT(a)Phủ định giá trị đúng/sai.NOT({Đã đóng})false

Văn bản

HàmCú phápMô tảVí dụKết quả
CONCATCONCAT(a, b, …)Nối các chuỗi lại; giá trị rỗng thành "".CONCAT({Họ}, " ", {Tên})"Nguyễn An"
UPPERUPPER(text)Chuyển thành chữ HOA.UPPER("abc")"ABC"
LOWERLOWER(text)Chuyển thành chữ thường.LOWER("ABC")"abc"
TRIMTRIM(text)Bỏ khoảng trắng đầu/cuối.TRIM(" a ")"a"
LENLEN(text)Số ký tự của chuỗi.LEN("Inforact")8
LEFTLEFT(text, n)Lấy n ký tự đầu.LEFT("Inforact", 3)"Inf"
RIGHTRIGHT(text, n)Lấy n ký tự cuối.RIGHT("Inforact", 3)"act"
MIDMID(text, bắt_đầu, n)Lấy n ký tự từ vị trí bắt_đầu (tính từ 1).MID("Inforact", 3, 4)"fora"
REPLACEREPLACE(text, bắt_đầu, n, mới)Thay n ký tự từ vị trí bắt_đầu bằng chuỗi mới.REPLACE("abcdef", 2, 3, "XY")"aXYef"
SUBSTITUTESUBSTITUTE(text, cũ, mới, [lần])Thay chuỗi cũ bằng mới; bỏ [lần] thì thay tất cả.SUBSTITUTE("a-b-c", "-", "+")"a+b+c"
FINDFIND(cần_tìm, trong, [từ])Vị trí xuất hiện (từ 1), phân biệt hoa/thường; không thấy trả 0.FIND("b", "abc")2
SEARCHSEARCH(cần_tìm, trong, [từ])Như FIND nhưng KHÔNG phân biệt hoa/thường.SEARCH("B", "abc")2
REPTREPT(text, n)Lặp chuỗi n lần.REPT("ab", 3)"ababab"
PROPERPROPER(text)Viết hoa chữ cái đầu mỗi từ.PROPER("hello world")"Hello World"
VALUEVALUE(text)Chuyển chuỗi số thành số; không parse được trả rỗng.VALUE("42.5")42.5
TT(x)Trả về x nếu là văn bản, ngược lại rỗng.T("hi")"hi"

Số

HàmCú phápMô tảVí dụKết quả
ROUNDROUND(số, [chữ_số])Làm tròn tới số chữ số thập phân.ROUND(3.14159, 2)3.14
ROUNDUPROUNDUP(số, [chữ_số])Làm tròn LÊN (xa số 0).ROUNDUP(1.01, 0)2
ROUNDDOWNROUNDDOWN(số, [chữ_số])Làm tròn XUỐNG (về số 0).ROUNDDOWN(1.99, 0)1
ABSABS(số)Trị tuyệt đối.ABS(-5)5
CEILCEIL(số)Làm tròn lên số nguyên gần nhất.CEIL(2.1)3
FLOORFLOOR(số)Làm tròn xuống số nguyên gần nhất.FLOOR(2.9)2
INTINT(số)Phần nguyên (làm tròn về âm vô cùng).INT(-1.1)-2
MODMOD(a, b)Số dư của a chia b.MOD(10, 3)1
POWERPOWER(a, b)a mũ b.POWER(2, 10)1024
SQRTSQRT(a)Căn bậc hai (a âm trả rỗng).SQRT(144)12
EXPEXP(a)e mũ a.EXP(0)1
LOGLOG(a, [cơ_số])Logarit của a theo cơ số (mặc định 10).LOG(1000)3
LNLN(a)Logarit tự nhiên (cơ số e).LN(1)0
MINMIN(a, b, …)Giá trị nhỏ nhất.MIN(3, 1, 2)1
MAXMAX(a, b, …)Giá trị lớn nhất.MAX(3, 1, 2)3
SUMSUM(a, b, …)Tổng các số (bỏ qua giá trị rỗng).SUM({Q1}, {Q2}, {Q3})60
AVERAGEAVERAGE(a, b, …)Trung bình cộng (bỏ qua giá trị rỗng).AVERAGE(2, 4, 6)4

Ngày & giờ

HàmCú phápMô tảVí dụKết quả
NOWNOW()Thời điểm hiện tại (ngày + giờ).NOW()"2026-07-06T10:00:00Z"
TODAYTODAY()Ngày hôm nay.TODAY()"2026-07-06"
DATEDATE(năm, tháng, ngày)Tạo ngày từ 3 thành phần.DATE(2026, 7, 6)"2026-07-06"
DATEADDDATEADD(ngày, n, 'days')Cộng/trừ khoảng thời gian (days/weeks/months/years/hours/minutes).DATEADD({Ngày}, 7, "days")"2026-07-13"
DATETIME_DIFFDATETIME_DIFF(a, b, 'days')Khoảng cách giữa hai mốc theo đơn vị.DATETIME_DIFF({Hạn}, TODAY(), "days")5
DATETIME_FORMATDATETIME_FORMAT(ngày, 'mẫu')Định dạng ngày theo mẫu (YYYY MM DD HH mm ss), giờ VN.DATETIME_FORMAT({Ngày}, "DD/MM/YYYY")"06/07/2026"
YEARYEAR(ngày)Năm (giờ VN).YEAR("2026-07-06")2026
MONTHMONTH(ngày)Tháng 1–12 (giờ VN).MONTH("2026-07-06")7
DAYDAY(ngày)Ngày trong tháng (giờ VN).DAY("2026-07-06")6
HOURHOUR(datetime)Giờ 0–23 (giờ VN).HOUR("2026-07-06T10:30:00Z")17
MINUTEMINUTE(datetime)Phút 0–59.MINUTE("2026-07-06T10:30:00Z")30
SECONDSECOND(datetime)Giây 0–59.SECOND("2026-07-06T10:30:45Z")45
WEEKDAYWEEKDAY(ngày)Thứ trong tuần: 1=Thứ Hai … 7=Chủ Nhật.WEEKDAY("2026-07-06")1
WEEKNUMWEEKNUM(ngày)Số tuần trong năm (ISO-8601).WEEKNUM("2026-01-01")1
WORKDAYWORKDAY(ngày, n)Cộng n ngày làm việc (bỏ Thứ Bảy/Chủ Nhật).WORKDAY("2026-07-06", 5)"2026-07-13"
WORKDAY_DIFFWORKDAY_DIFF(a, b)Số ngày làm việc giữa hai ngày (có dấu).WORKDAY_DIFF("2026-07-06", "2026-07-13")5

Kiểm tra

HàmCú phápMô tảVí dụKết quả
BLANKBLANK()Giá trị rỗng.IF({Số} > 0, {Số}, BLANK())(rỗng)
ISBLANKISBLANK(x)Đúng nếu x rỗng.ISBLANK({Ghi chú})true

Tổng hợp chéo bảng

HàmCú phápMô tảVí dụKết quả
FILTERFILTER({Bảng.Cột}, điều_kiện)Chọn giá trị một cột ở BẢNG KHÁC theo điều kiện. Luôn phải bọc trong một hàm tổng hợp (SUM/COUNT/AVERAGE/MIN/MAX/CONCAT/AND/OR).SUM(FILTER({Đơn hàng.tiền}, {Đơn hàng.Mã KH} = {Mã KH}))1.400.000
COUNTCOUNT(FILTER(…))Đếm số bản ghi khớp điều kiện của FILTER(). Chỉ dùng được cùng FILTER().COUNT(FILTER({Đơn hàng.tiền}, {Đơn hàng.Mã KH} = {Mã KH}))3

FILTER() luôn phải đứng trong một hàm tổng hợp

FILTER() một mình không phải là một giá trị — nó là một tập bản ghi của bảng khác. Base sẽ báo lỗi nếu bạn đặt FILTER() trực tiếp làm công thức của cột; nó chỉ hợp lệ khi làm đối số của SUM/COUNT/AVERAGE/ MIN/MAX/CONCAT/AND/OR, ví dụ SUM(FILTER(...)). Điều kiện lọc bên trong là các phép so sánh nối bằng AND/OR/NOT, vế trái là một cột của bảng kia, vế phải là hằng số, một cột của bảng này, hoặc TODAY().

Ví dụ hàm lồng nhau

Sức mạnh thật sự của Formula nằm ở việc lồng nhiều hàm vào nhau trong một công thức — kết quả của hàm này làm đầu vào cho hàm khác. Ba ví dụ dưới đây lấy từ dữ liệu vận hành thật của một công ty thương mại, mỗi ví dụ đều đã được thử trực tiếp trong dialog và cho ra "Công thức hợp lệ".

Cảnh báo đơn hàng trễ giao

Trên bảng Đơn hàng, muốn có một cột tự động cảnh báo đơn nào đã quá hạn giao mà vẫn chưa hoàn thành — vừa cần so ngày (DATETIME_DIFF/TODAY), vừa cần kết hợp hai điều kiện (AND), vừa cần ghép chữ hiển thị số ngày trễ (CONCAT):

IF(
  AND(
    {Trạng thái} <> "Hoàn thành",
    DATETIME_DIFF(TODAY(), {Ngày giao dự kiến}, "days") > 0
  ),
  CONCAT("Trễ ", DATETIME_DIFF(TODAY(), {Ngày giao dự kiến}, "days"), " ngày"),
  "Đúng hạn"
)

IF là hàm ngoài cùng; nhánh điều kiện của nó là một AND gồm hai vế; nhánh kết quả "trễ" của nó lại là một CONCAT có chứa DATETIME_DIFF bên trong — ba tầng lồng nhau trong cùng một công thức.

Công thức cảnh báo trễ giao lồng IF, AND, CONCAT, DATETIME_DIFF và TODAY
IF lồng AND lồng DATETIME_DIFF/TODAY, và CONCAT lồng DATETIME_DIFF — xem trước cho kết quả thật trên từng đơn hàng.

Nhãn khách VIP theo doanh thu

Vẫn trên bảng Đơn hàng, muốn gắn nhãn ưu đãi cho các đơn có doanh thu từ 10 triệu trở lên, kèm số tiền tiết kiệm được đã làm tròn:

IF(
  {Doanh thu} >= 10000000,
  CONCAT("VIP - tiết kiệm ", ROUND({Doanh thu}*0.05, 0), "đ"),
  "Khách thường"
)

Ở đây IF lồng CONCAT, và CONCAT lại lồng ROUND cùng một phép tính số học ({Doanh thu}*0.05) ngay bên trong nó.

Công thức nhãn khách VIP lồng IF, CONCAT và ROUND
IF lồng CONCAT lồng ROUND — mỗi đơn hàng đủ điều kiện hiện luôn số tiền tiết kiệm đã làm tròn.

Phân loại khách hàng thân thiết

Trên bảng Khách hàng, muốn phân loại khách thành 3 mức dựa trên độ tín nhiệm và thời gian hợp tác — cần một IF lồng bên trong nhánh else của một IF khác (kiểu bậc thang, thay cho việc viết nhiều cột phụ):

IF(
  AND({Tín nhiệm} >= 4, DATETIME_DIFF(TODAY(), {Ngày hợp tác}, "days") > 365),
  "Khách hàng thân thiết",
  IF({Tín nhiệm} >= 4, "Khách hàng tốt", "Khách hàng thường")
)
Công thức phân loại khách hàng lồng hai IF và một AND chứa DATETIME_DIFF/TODAY
IF lồng IF ở nhánh else, điều kiện ngoài cùng là AND chứa DATETIME_DIFF/TODAY — phân loại khách thành 3 mức chỉ với một công thức.

Mẹo khi công thức lồng nhiều tầng

Công thức càng lồng sâu càng khó đọc lại sau này. Đặt tên cột rõ ràng, và nếu một công thức bắt đầu quá dài, cân nhắc tách thành nhiều cột Formula nhỏ hơn rồi tham chiếu cột này vào cột kia — dễ đọc và dễ sửa hơn một công thức khổng lồ.

Formula là một trong những kiểu cột tính toán của Base — xem thêm về tạo bảng và chọn kiểu cột nếu bạn chưa quen với các kiểu cột khác, hoặc liên kết bảng để hiểu cách một bảng tham chiếu bảng khác trước khi dùng FILTER().