Google Sheet API v4 获取空单元格

Googlesheet APIv4 getting empty cells

我有一个 googlesheet,其中一列可能不包含任何信息。在遍历行并查看该列时,如果该列为空白,则它没有 returning 任何内容。更糟糕的是,如果我获取整行并包括那个公共项,比如获取 5 列,那么当任何列为空时我只返回 4 列。如果我得到一行列并且列中的一个单元格为空,我该如何 return NULL 或空字符串?

// Build a new authorized API client service.
Sheets service = GoogleSheets.getSheetsService();
range = "Functional Users!A3:E3";
response = service.spreadsheets().values().get(spreadsheetId, range).execute();
values = response.getValues();
cells = values.get(0);

我得到了一行中的 5 个单元格。 cells.size() 应该总是 return 五。但是,如果 5 个单元格中的任何一个为空白,它将减少 return 个单元格。假设只有 B3 的单元格是空的。 cells.size() 将为 4。下一次迭代,我得到 A4:E4 并且单元格 D4 为空。同样,cells.size() 将为 4。无法知道缺少哪个单元格。如果 A4 AND D4 AND E4 为空,则 cells.size() 将为 2。

无论单元格是否为空,如何将其添加到 return 5 个单元格?

我已经涉足 Sheetsv4,这确实是当您读取一系列包含空数据的单元格时的行为。似乎这就是它的设计方式。如 Reading data docs 中所述:

Empty trailing rows and columns are omitted.

所以如果你能找到一种方法来写一个代表 'empty values' 的字符,比如零,那么这就是一种方法。

我解决这个问题的方法是将值转换为 Pandas 数据框。我在我的 Google 表格中获取了我想要的特定列,然后将这些值转换为 Pandas 数据框。将数据集转换为 Pandas 数据框后,我进行了一些数据格式化,然后将数据框转换回列表。通过将列表转换为 Pandas 数据框,每一列都会被保留。 Pandas 已经为空的尾随行和列创建了空值。但是,我还需要转换具有空值的非尾随行以保持一致性。

# Authenticate and create the service for the Google Sheets API
credentials = ServiceAccountCredentials.from_json_keyfile_name(KEY_FILE_LOCATION, SCOPES)
http = credentials.authorize(Http())
discoveryUrl = ('https://sheets.googleapis.com/$discovery/rest?version=v4')
service = discovery.build('sheets', 'v4',
    http=http,discoveryServiceUrl=discoveryUrl)

spreadsheetId = 'id of your sheet'
rangeName = 'range of your dataset'
result = service.spreadsheets().values().get(
    spreadsheetId=spreadsheetId, range=rangeName).execute()
values = result.get('values', [])

#convert values into dataframe
df = pd.DataFrame(values)

#replace all non trailing blank values created by Google Sheets API
#with null values
df_replace = df.replace([''], [None])

#convert back to list to insert into Redshift
processed_dataset = df_replace.values.tolist()

我在使用工作表 api 的 V4 时遇到了同样的问题,但能够使用范围末尾的额外列和 values.getvalueRenderOption 参数解决此问题] API

给定三列 A、B 和 C,其中任何一列都可能包含空值,添加一个附加列 D 并在此处添加任意值,例如 'blank'.

确保捕获范围内的新列并添加附加参数,

valueRenderOption: 'FORMATTED_VALUE'

您应该以类似这样的调用结束:

sheets.spreadsheets.values.get({
  spreadsheetId: SOME_SHEET_ID,
  range: "AUTOMATION!A:D",
  valueRenderOption: 'FORMATTED_VALUE'
}, (err, res) => {})

这将为您提供每个值的长度一致的数组,并在空单元格值的位置返回一个空白字符串“”。

我能找到的唯一解决方案是编写您自己的函数:

def _safe_get(data, r, c):   
    try:
        return data[r][c]
    except IndexError:
        return ''

def read(range_name, service):
    result = service[0].spreadsheets().values().get(spreadsheetId=service[1],
                                                range=range_name).execute()
    return result.get('values', [])

def safe_read(sheet, row, col, to_row='', to_col='', service=None):
        range_name = '%s!%s%i:%s%s' % (sheet, col, row, to_col, to_row)
        data = read(range_name, service)

    if to_col == '':
        cols = max(len(line) for line in data)
    else:
        cols = ord(to_col.lower()) - ord(col.lower()) + 1
    if to_row == '':
        rows = len(data)
    else:
        rows = to_row - row + 1

    return [[_safe_get(data, r, c)
             for c in range(cols)]
            for r in range(rows)]

我知道这太晚了,但为了防止将来遇到此问题的其他人想要修复它,我将分享我为解决此问题所做的工作。 我所做的是将我正在寻找的单元格范围的长度增加一个。然后在我正在阅读的 Google 电子表格中,我添加了一行“."s in the extra column (The column added to the array now that the desired range of cells has increased). Then I protected that line of periods so that it can't be changed from the "”。 这种方式为您提供了一个数组,其中包含您要查找的所有内容,包括空结果,但确实会将数组大小增加 1。但是如果这让您感到困扰,您可以创建一个没有数组最后一个索引的新数组。

如果您从 google sheet API v4 中拉出一个范围,则如果空行数据位于所选范围的开头或中间,则包含空行数据。 仅省略范围末尾没有数据的单元格。使用此假设,您可以 'fill' 应用代码中的无数据单元格。

例如,如果您选择 A1:A5 而 A1 没有值,它仍将在行数据中返回为 {}

如果缺少 A5,那么您将得到一个长度为 4 的数组,因此知道要填充空的 A5。 如果 A4 和 A5 为空,那么您将得到一个长度为 3 的数组,依此类推。

如果范围 none 包含数据,那么您将收到一个空对象。

如果行中的最后一个单元格有值,则该行将完全返回 例如:

行数:

|Nick|29 years|Minsk|
|Mike|        |Pinsk|
|Boby|        |     |

Return:

[
  ["Nick", "29 years", "Minsk"],
  ["Mike", "", "Pinsk"]
  ["Boby"]
]

因此,当您添加一个包含空单元格而不是空单元格(""null)的新行时,只需使用 space " "

然后当您读取值时,只需将 space " " 中的所有项目映射到空 ""

行数:

|Nick|29 years|Minsk|
|Mike|        |Pinsk|
|Boby|        |"  " |

Return:

[
  ["Nick", "29 years", "Minsk"],
  ["Mike", "", "Pinsk"]
  ["Boby", "", " "]
]

只需添加:

values.add("");

之前:

cells = values.get(0);

这将确保您不会因为空白单元格或行而查询空列表。

另一个选项是遍历返回的行,检查行的长度并附加您期望返回的任何数据。我发现这比将垃圾数据添加到我的数据集更可取。

我来晚了,但还有另一种选择:

def read_sheet(service, SPREADSHEET_ID, range) -> pd.DataFrame:

    result = service.spreadsheets().values().get(spreadsheetId=SPREADSHEET_ID, range=range).execute()

    rows = result.get('values', [])

    df = pd.DataFrame(rows[0:])

    df.columns = df.iloc[0]

    df = df.drop(axis=0, index=0)

    return df

要使此解决方案生效,您需要在要阅读的电子表格的所有列中输入 headers(列名)。它将加载没有 headers(列名)规范的 pandas df,用第一行替换列名,然后删除它。

Sheets API V4,应该 return 所有空白直到最后填充的列。

这将填补空白:

values = result.get('values', [])
print(values[1:5]) # [['Spinach Lasagna', '10', '5', '', 'x'], ['Hot Dish', '10', '5', '', '', '', 'x'], ['Tuna-Noodle Casserole', '10', '5', '', 'x', '', '', 'x'], ['Sausage and Peppers', '10', '3', '', '', '', '', '', 'x']]

n_col = 14                                # hard code
n_col = max([len(i) for i in values])     # if last column is occupied at least once
n_col = len(values[0])                    # if you have header

values = [lst + ([''] * (n_col - len(lst))) for lst in values]

print(values[1:4]) # [['Spinach Lasagna', '10', '5', '', 'x', '', '', '', '', '', '', '', '', ''], ['Hot Dish', '10', '5', '', '', '', 'x', '', '', '', '', '', '', ''], ['Tuna-Noodle Casserole', '10', '5', '', 'x', '', '', 'x', '', '', '', '', '', '']]