0

Find Rows

by
Published today

Find the rows of a worksheet whose value in a column matches a lookup value.

Script gsheets Verified

The script

Submitted by hugo989 Typescript (fetch-only)
Verified 47 minutes ago
1
//native
2

3
export type DynSelect_sheet_name = string
4

5
// Dropdown of the spreadsheet's worksheet (tab) names.
6
export async function sheet_name(auth: RT.Gsheets, spreadsheet_id: string) {
7
  const response = await fetch(
8
    `https://sheets.googleapis.com/v4/spreadsheets/${spreadsheet_id}?fields=sheets.properties.title`,
9
    {
10
      headers: {
11
        Authorization: `Bearer ${auth.token}`,
12
        Accept: "application/json",
13
      },
14
    }
15
  )
16
  if (!response.ok) {
17
    throw new Error(`${response.status} ${await response.text()}`)
18
  }
19
  const { sheets } = (await response.json()) as {
20
    sheets: { properties: { title: string } }[]
21
  }
22
  return sheets.map((s) => ({
23
    value: s.properties.title,
24
    label: s.properties.title,
25
  }))
26
}
27

28
/**
29
 * Find Rows
30
 * Find the rows whose value in a column equals the given value (exact match on the displayed value). Row 1 is read as the header row; `column` is a header name or a column letter. Returns each match's 1-based `row_number` and its values keyed by header.
31
 */
32
export async function main(
33
  auth: RT.Gsheets,
34
  spreadsheet_id: string,
35
  sheet_name: DynSelect_sheet_name,
36
  column: string,
37
  value: string
38
) {
39
  const range = encodeURIComponent(`'${sheet_name.replaceAll("'", "''")}'`)
40
  const response = await fetch(
41
    `https://sheets.googleapis.com/v4/spreadsheets/${spreadsheet_id}/values/${range}`,
42
    {
43
      headers: {
44
        Authorization: `Bearer ${auth.token}`,
45
        Accept: "application/json",
46
      },
47
    }
48
  )
49

50
  if (!response.ok) {
51
    throw new Error(`${response.status} ${await response.text()}`)
52
  }
53

54
  const { values = [] } = (await response.json()) as { values?: string[][] }
55
  const [headers = [], ...rows] = values
56

57
  // Header name first, then column letter (A, B, …, AA).
58
  let index = headers.indexOf(column)
59
  if (index === -1 && /^[A-Za-z]{1,3}$/.test(column)) {
60
    index =
61
      [...column.toUpperCase()].reduce(
62
        (n, c) => n * 26 + c.charCodeAt(0) - 64,
63
        0
64
      ) - 1
65
  }
66
  if (index === -1) {
67
    throw new Error(
68
      `Column "${column}" not found in header row: ${headers.join(", ")}`
69
    )
70
  }
71

72
  return rows.flatMap((row, i) =>
73
    (row[index] ?? "") === value
74
      ? [
75
          {
76
            row_number: i + 2,
77
            values: Object.fromEntries(
78
              headers.map((h, j) => [h, row[j] ?? ""])
79
            ),
80
          },
81
        ]
82
      : []
83
  )
84
}
85