尝试创建对象列表时出错 - 索引超出范围 (Google.APIs.Sheets.v4.Data.ValueRange)

Error trying to create a List of Object - Index out of Range (Google.APIs.Sheets.v4.Data.ValueRange)

我无法理解这些嵌套列表。

为了 Google 工作表 API 插入数据,我必须根据我的理解传递一个列表列表,代表行和列。

我怎么不知道如何加载列表中的值。

        Dim requestBody As New ValueRange()

        Dim rowCount As Integer = 2

        requestBody.Values = New List(Of IList(Of Object))() From {New List(Of Object)()}

        requestBody.Values(0).Add(1)
        requestBody.Values(0).Add(2)
        requestBody.Values(0).Add(3)
        requestBody.Values(0).Add(4)
        requestBody.Values(0).Add(5)
        requestBody.Values(1).Add("a")
        requestBody.Values(1).Add("b")
        requestBody.Values(1).Add("c")
        requestBody.Values(1).Add("d")
        requestBody.Values(1).Add("e")

当我到达第二个值(行)时,出现错误:索引超出范围。

System.ArgumentOutOfRangeException: 'Index was out of range. Must be non-negative and less than the size of the collection.'

感谢您的帮助。

PS 如果有人可以分享一个将 DataTable 转换为该对象(列表列表)的示例,那么循环遍历行并手动构建该对象会容易得多,将永远感激不已.

https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/append

更新:这是我要创建的函数的完整代码。

Imports System.IO
Imports Google.Apis.Auth.OAuth2
Imports Google.Apis.Services
Imports Google.Apis.Sheets.v4
Imports Google.Apis.Sheets.v4.Data

Namespace Settings
    Public Class SettingsPage
        Inherits System.Web.UI.Page
        Dim _connstring As String

        Dim googleSecretJsonFilePath = Server.MapPath("GoogleSecret\GoogleSecret.json")
        Dim applicationName = "OPT Web Services"
        Dim scopes As String() = {SheetsService.Scope.Spreadsheets, SheetsService.Scope.Drive, SheetsService.Scope.DriveFile}
        Dim googleService = New GoogleService(googleSecretJsonFilePath, applicationName, scopes)
        Dim spreadSheetId = "14N-1R##########################sCWA7U" 'Private Live Sheet

        Protected Sub btnSendVersions_Click(sender As Object, e As EventArgs) Handles btnSendVersions.Click
            'TODO: Append KS_SedonaSync_Version to Google Docs - Tab
            'TODO: Append SS_Version to Google Docs

            Dim range = "'Customer OPT Versions'!A:E"
            'A (0)  - OPT_Customer_Number
            'B (1)  - Version_Id
            'C (2)  - Date_Installed
            'D (3)  - SedonaSync_Event_Id
            'E (4)  - Version

            Dim ds As DataSet = Master.OPTWebConfig.GetVersionList(_connstring)

            Dim sheetService = googleService.GetSheetsService()

            Dim valueInputOption As SpreadsheetsResource.ValuesResource.AppendRequest.ValueInputOptionEnum = SpreadsheetsResource.ValuesResource.AppendRequest.ValueInputOptionEnum.RAW
            Dim insertDataOption As SpreadsheetsResource.ValuesResource.AppendRequest.InsertDataOptionEnum = SpreadsheetsResource.ValuesResource.AppendRequest.InsertDataOptionEnum.INSERTROWS

            Dim requestBody As New ValueRange()

            'Update OPT Version Numbers
            Dim rowCount As Integer = ds.Tables("Versions").Rows.Count
            'TODO: Make this work: requestBody.Values = ds.Tables("Versions").Rows

            'Test Adding Multiple Rows, May need to loop through DataTable rows if we cannot find a way to convert the DataTable.
            requestBody.Values = New List(Of IList(Of Object))() From {New List(Of Object)()}
            requestBody.Values(0).Add(1)
            requestBody.Values(0).Add(2)
            requestBody.Values(0).Add(3)
            requestBody.Values(0).Add(4)
            requestBody.Values(0).Add(5)
            requestBody.Values(1).Add("a")
            requestBody.Values(1).Add("b")
            requestBody.Values(1).Add("c")
            requestBody.Values(1).Add("d")
            requestBody.Values(1).Add("e")

            Dim request As SpreadsheetsResource.ValuesResource.AppendRequest = sheetService.Spreadsheets.Values.Append(requestBody, spreadSheetId, range)
            request.ValueInputOption = valueInputOption
            request.InsertDataOption = insertDataOption
            Dim response = request.Execute()

            'TODO: Mark Rows in ds.Tables("Versions") as Sent_To_OPT = "Y" if Response is 200:OK
        End Sub
    End Class

    Public Class GoogleService
        Private ReadOnly _googleSecretJsonFilePath As String
        Private ReadOnly _applicationName As String
        Private ReadOnly _scopes As String()
        Public Sub New(googleSecretJsonFilePath As String, applicationName As String, scopes As String())
            _googleSecretJsonFilePath = googleSecretJsonFilePath
            _applicationName = applicationName
            _scopes = scopes
        End Sub
        Public Function GetGoogleCredential() As GoogleCredential
            Dim credential As GoogleCredential
            Using stream = New FileStream(_googleSecretJsonFilePath, FileMode.Open, FileAccess.Read)
                credential = GoogleCredential.FromStream(stream).CreateScoped(_scopes)
            End Using
            Return credential
        End Function
        Public Function GetSheetsService() As SheetsService
            Dim credential = GetGoogleCredential()
            Dim Base As New BaseClientService.Initializer
            Base.HttpClientInitializer = credential
            Base.ApplicationName = _applicationName
            Dim sheetsService = New SheetsService(Base)
            Return sheetsService
        End Function
    End Class
End Namespace

使用调试器很容易看出问题所在。我无法访问那个 API,所以下面只使用 List(Of List(Of Object)),这就是问题所在:在这行代码之后:

Dim requestBody As New List(Of IList(Of Object)) From {New List(Of Object)()}

调试器显示:

因此 requestBody.Values 集合中只有一个 "row"(这是 From {New List(Of Object)() 的结果)。没有添加其他行。

' create collection, add row(0)
Dim Values As New List(Of IList(Of Object)) From {New List(Of Object)()}

Dim rowCount As Integer = 2

Values(0).Add(1)
Values(0).Add(2)
...

' add row(1)
Values.Add(New List(Of Object))
Values(1).Add("a")
Values(1).Add("b")
...

对于这样的事情,我的偏好是做所有相同的事情并省略 From... 初始值设定项并以相同的方式添加所有行,这样很容易发生什么。错误的、未使用的 rowCount 使它看起来像是一个循环,因此将它们全部相同会使事情变得更容易。结果:

那有没有更干净的选择?

        Dim rowCount As Integer = ds.Tables("Versions").Rows.Count
        requestBody.Values = New List(Of IList(Of Object))()
        Dim i As Integer = 0
        For Each row As DataRow In ds.Tables("Versions").Rows
            requestBody.Values.Add(New List(Of Object))
            requestBody.Values(i).Add(row.Item(0))
            requestBody.Values(i).Add(row.Item(1))
            requestBody.Values(i).Add(row.Item(2))
            requestBody.Values(i).Add(row.Item(3))
            requestBody.Values(i).Add(row.Item(4))
            i = i + 1
        Next

'获取 Internet 日志文件 ID ID()

    ' If modifying these scopes, delete your previously saved credentials
    ' at ~/.credentials/sheets.googleapis.com-dotnet-quickstart.json
    Dim Scopes As String = SheetsService.Scope.SpreadsheetsReadonly
    Dim ApplicationName As String = "Google Sheets API .NET Quickstart"

    Dim credential2 As UserCredential
    Dim stream2 = New FileStream(My.Application.Info.DirectoryPath + "\client_secret.json", FileMode.Open, FileAccess.Read)
    Dim credPath As String = My.Application.Info.DirectoryPath + "\"
    credential2 = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream2).Secrets, {Scopes}, "user", CancellationToken.None, New FileDataStore(credPath, True)).Result
    stream2.Close()

    ' Create Google Sheets API service.
    Dim Service = New SheetsService(New BaseClientService.Initializer() With {.HttpClientInitializer = credential2, .ApplicationName = ApplicationName})

    Dim ranges As IList
    Dim includeGridData As Boolean = False
    Dim request2 As SpreadsheetsResource.GetRequest = Service.Spreadsheets.Get(IDREGISTRO)
    request2.Ranges = ranges
    request2.IncludeGridData = includeGridData

    'TODOS LOS DATOS
    Dim response As Data.Spreadsheet = request2.Execute()
    Dim totalrows = response.Sheets(0).Properties.GridProperties.RowCount
    Dim totalcolumsn = response.Sheets(0).Properties.GridProperties.ColumnCount
    Dim Hoja = response.Sheets(0).Properties.Title
    Dim Range As String = Hoja + "!A2:" + "L" + totalrows.ToString

    ' Define request parameters.
    Dim request As SpreadsheetsResource.ValuesResource.GetRequest = Service.Spreadsheets.Values.Get(IDREGISTRO, Range)
    Dim response2 As ValueRange = request.Execute()
    Dim values = response2.Values
    ' The ID of the spreadsheet to add row.
    Dim spreadsheetId As String = IDREGISTRO


    Dim r1 As String = Hoja & "!A" & totalrows & ":L" & totalrows

    ' Define one row
    Dim values2 As List(Of IList(Of Object)) = New List(Of IList(Of Object))()
    Dim obj As IList(Of Object) = New List(Of Object)()
    obj.Add(dt)
    obj.Add(TextBox1.Text)
    obj.Add(TextBox2.Text)
    obj.Add(TextBox6.Text)
    obj.Add(TextBox7.Text)
    obj.Add(TextBox3.Text)
    obj.Add(TextBox5.Text)
    obj.Add(TextBox4.Text)
    obj.Add(combobox1.Text)
    obj.Add(DIRMAC)
    obj.Add("NO")
    obj.Add(My.Application.Info.AssemblyName)
    values2.Add(obj)

    Dim valueInputOption As SpreadsheetsResource.ValuesResource.AppendRequest.ValueInputOptionEnum = SpreadsheetsResource.ValuesResource.AppendRequest.ValueInputOptionEnum.RAW
    Dim insertDataOption As SpreadsheetsResource.ValuesResource.AppendRequest.InsertDataOptionEnum = SpreadsheetsResource.ValuesResource.AppendRequest.InsertDataOptionEnum.INSERTROWS
    Dim request4 As SpreadsheetsResource.ValuesResource.AppendRequest = Service.Spreadsheets.Values.Append(New ValueRange With {.Values = values2}, spreadsheetId, r1)
    request4.ValueInputOption = valueInputOption
    request4.InsertDataOption = insertDataOption
    Dim response4 = request4.Execute()