web-dev-qa-db-ja.com

Google Sheet APIv4が空のセルを取得する

列に情報が含まれていない可能性のあるGoogleスプレッドシートがあります。行を繰り返し処理してその列を確認しているときに、列が空白の場合、何も返されません。さらに悪いことに、完全な行を取得し、その一般的なものを含めると、たとえば5列を取得すると、いずれかの列が空の場合に4列しか返されません。列の行を取得していて、列のセルの1つが空の場合、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を返す必要があります。ただし、5つのセルのいずれかが空白の場合、返されるセルは少なくなります。 B3のセルだけが空であると言います。 cells.size()は4になります。次の反復では、A4:E4を取得し、セルD4は空です。繰り返しますが、cells.size()は4になります。どのセルが欠落しているかを知る方法はありません。 A4 AND D4 AND E4が空の場合、cells.size()は2になります。

空のセルに関係なく5つのセルを返すにはどうすればよいですか?

14
GregMa

Sheetsv4に手を出しましたが、これは実際、空のデータを持つセルの範囲を読み取っているときの動作です。これが設計された方法のようです。 データドキュメントの読み取り で述べられているように:

空の末尾の行と列は省略されています。

したがって、ゼロのように「空の値」を表す文字を書く方法を見つけることができれば、それはそれを行う1つの方法になります。

5
noogui

この問題を解決する方法は、値をPandasデータフレームに変換することでした。Googleスプレッドシートに必要な特定の列をフェッチしてから、それらの値をPandasデータフレーム。データセットをPandasデータフレームに変換したら、データの書式設定を行ってから、データフレームをリストに戻しました。リストをPandasデータフレーム、各列は保持されます。Pandasは、空の末尾の行と列に対してすでにnull値を作成しています。ただし、一貫性を保つために、末尾以外の行もnull値に変換する必要がありました。 。

# 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()
7
Chase Wright

Sheets APIのV4を使用して同じ問題が発生しましたが、範囲の最後にある追加の列とvalues.getAPIのvalueRenderOption引数を使用してこれを回避できました。

A、B、Cの3つの列があり、いずれにもnull値が含まれている可能性がある場合は、列Dを追加し、ここに「空白」などの任意の値を追加します。

範囲内の新しい列をキャプチャし、追加のパラメータを追加してください。

valueRenderOption: 'FORMATTED_VALUE'

次のような呼び出しが発生するはずです。

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

これにより、値ごとに一貫した長さの配列が得られ、空のセル値の代わりに空白の文字列 ""が返されます。

2
James

これは非常に遅いことは知っていますが、将来この問題を抱えている他の誰かがそれを修正したい場合に備えて、これを超えて作業するために私がしたことを共有します。私がしたことは、探していたセルの範囲の長さを1つ増やすことでした。次に、読み上げていたGoogleスプレッドシート内で、追加の列に「。」の行を追加しました(セルの目的の範囲が増えたため、列が配列に追加されました)。次に、そのピリオドの行を保護して、「。」から変更できないようにしました。この方法では、nullの結果を含め、探しているすべてのものを含む配列が得られますが、配列サイズは1増加します。ただし、それが気になる場合は、配列の最後のインデックスなしで新しい配列を作成できます。

1
Roy Ernster

Google sheet API v4から範囲を取得すると、空の行データISは、選択した範囲の最初または中央にある場合に含まれます。データがないセルのみ範囲の終わりは省略されます。この仮定を使用して、アプリコードのデータセルを「埋める」ことができます。

たとえば、A1:A5を選択し、A1に値がない場合でも、行データに{}として返されます。

A5が欠落している場合は、長さ4の配列があるため、空のA5を埋めることを知ってください。 A4とA5が空の場合、長さ3などの配列があります。

範囲のいずれにもデータが含まれていない場合は、空のオブジェクトを受け取ります。

0
Jafferwaffer

行の最後のセルに値がある場合、その行は完全に返されます。次に例を示します。

行:

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

戻り値:

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

したがって、empty(""またはnull)の代わりに空のセルを含む新しい行を追加するときは、スペース" "を使用してください。

そして、値を読み取るときは、すべてのアイテムをスペース" "から空の""にマップするだけです。

行:

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

戻り値:

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

私が見つけた唯一の解決策は、独自の関数を作成することです。

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