尝试创建对象列表时出错 - 索引超出范围 (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()
我无法理解这些嵌套列表。
为了 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()