我有一个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个单元格?
答案 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);
这将确保您不会因为空白单元格或一行而查询空列表。