Googlesheet APIv4获取空单元格

时间:2016-07-18 17:25:03

标签: google-sheets google-sheets-api

我有一个googlesheet,其中一列可能不包含任何信息。在遍历行并查看该列时,如果列为空,则它不会返回任何内容。更糟糕的是,如果我得到一个完整的行并包括那个常见的,比如获得5列,当任何列为空时,我只返回4列。如果我获得一行列并且列中的一个单元格为空,我该如何返回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()应该总是返回五。但是,如果5个细胞中的任何一个是空白的,它将返回更少的细胞。假设只有B3的单元格为空。 cells.size()将为4.下一次迭代,我得到A4:E4,单元格D4为空。同样,cells.size()将是4.无法知道哪个单元格丢失。如果A4和D4和E4为空,则cells.size()将为2.

无论空单元格如何,如何让它返回5个单元格?

10 个答案:

答案 0 :(得分:6)

我解决这个问题的方法是将值转换为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 = dataset.replace([''], [None])

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

答案 1 :(得分:5)

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

  

省略空尾随行和列。

因此,如果你能找到一种方法来写一个代表'空值'的字符,比如零,那么这将是一种方法。

答案 2 :(得分:1)

我使用表格api的V4遇到了相同的问题,但是能够使用范围末尾的额外列和valueRenderOption API的values.get参数来解决此问题

给出三个列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) => {})

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

答案 3 :(得分:1)

如果您从Google Sheet API v4中拉出一个范围,则在选定范围的开头或中间会包含空行数据。 仅忽略范围末尾没有数据的单元格。使用此假设,您可以“填充”应用程序代码中没有数据单元。

例如,如果您选择A1:A5且A1没有值,那么它仍将以{}的形式返回到行数据中。

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

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

答案 4 :(得分:0)

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

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)]

答案 5 :(得分:0)

我知道这太迟了,但是以防万一将来有其他问题的人想要解决此问题,我将分享我为解决此问题所做的工作。 我所做的就是将要查找的单元格范围的长度增加了一个。然后,在我正在阅读的Google Spreadsheet中,我在额外的列中添加了一行“。”(由于所需单元格的范围已增加,因此该列已添加到数组中)。然后,我保护了那行句号,以便不能将其从“。”更改。 这种方法为您提供了一个数组,其中包含您要查找的所有内容,包括空结果,但确实使数组大小增加了1。但是,如果这样困扰您,您可以在不使用数组最后一个索引的情况下新建一个数组。 >

答案 6 :(得分:0)

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

行:

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

返回:

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

因此,当您添加带有空单元格而不是空(""null)的新行时,只需使用空格" "

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

行:

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

返回:

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

答案 7 :(得分:0)

另一个选择是遍历返回的行,检查行的长度,并附加期望返回的任何数据。我发现这比向我的数据集中添加垃圾数据更好。

答案 8 :(得分: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

要使此解决方案起作用,您需要在要阅读的电子表格的所有列中添加标题(列名称)。它将加载一个没有标题(列名)规范的 Pandas df,用第一行替换列名,然后将其删除。

答案 9 :(得分:-1)

只需添加:

values.add("");

之前:

cells = values.get(0);

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