【问题标题】:Error trying to create a List of Object - Index out of Range (Google.APIs.Sheets.v4.Data.ValueRange)尝试创建对象列表时出错 - 索引超出范围 (Google.APIs.Sheets.v4.Data.ValueRange)
【发布时间】:2017-07-14 16:13:00
【问题描述】:

我无法将这些嵌套列表包裹起来。

为了让 Google Sheets 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

【问题讨论】:

    标签: .net vb.net google-api google-api-dotnet-client google-sheets-api


    【解决方案1】:

    用调试器很容易看出什么是错误的。我无权访问该 API,因此以下代码仅使用 List(Of List(Of Object)),这就是问题所在:在这行代码之后:

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

    调试器显示:

    所以requestBody.Values 集合中只有一个“行”(这是由于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 使它看起来像是一个循环,因此将它们都做同样的事情也会更容易。结果:

    【讨论】:

    • 好吧,我不得不承认我不知道我在用 From 语句做什么。你的例子更有意义。现在我至少可以理解发生了什么。像魅力一样工作。
    • 你是正确的,rowCount 是为循环加载行设置的。但是我已经在 DataTable 对象中有行。我可以大胆地问一下您是否对如何在不经过循环的情况下将 DataTable 传输到 Values 对象有任何想法?
    • 您可以使用一些 linq 选择一件事,然后选择另一件事。还有一个循环,不是你必须写的。
    • 使用 linq 会比下面列出的方法提高性能吗?我必须一次加载大约 1000 行。
    • 1000 行无关紧要。由于可以延迟执行,因此 Linq 可以更高效地处理数十万个项目。
    【解决方案2】:

    那么有没有更清洁的选择?

            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
    

    【讨论】:

    • 这确实是一个不同的问题,而不是原始帖子的答案。 SO 对演变成新问题的问题皱眉,因为它使不相关/新问题难以回答,其他人也难以搜索
    • 明白。好的,谢谢,我将在新线程中发布。再次感谢。
    【解决方案3】:

    'OBTIENE EL ID DEL ARCHIVO REGISTRO EN INTERNET 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()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-16
      • 1970-01-01
      • 2018-04-30
      • 1970-01-01
      • 1970-01-01
      • 2017-04-20
      • 1970-01-01
      相关资源
      最近更新 更多