I'm trying to update values in a Google Spreadsheet, The code executes up to the addRequest.Execute(); however, it does not run the execute statement.
This does work if i run a Append Request, however im not trying to append, im trying to update.
I have the following Scopes for the program static readonly string[] Scope = { SheetsService.Scope.Spreadsheets, DriveService.Scope.Drive};
var range = $"{ClashImport[i][0].ToString()}!B7:F106";
var REALInsertList = new sData.ValueRange();
var InsertList = new List<object>();
for (int n = 0; n < DataImport[i].Count; n++) {
InsertList.Add(DataImport[i][n].AccountName);
InsertList.Add(DataImport[i][n].AccountID);
InsertList.Add(DataImport[i][n].Banned);
InsertList.Add(DataImport[i][n].Suspended);
InsertList.Add(DataImport[i][n].History);
}
REALInsertList.Values = new List<IList<object>> { InsertList };
var addRequest = sheetsService.Spreadsheets.Values.Update(REALInsertList, SheetToImportTo, range);
addRequest.ValueInputOption = SpreadsheetsResource.ValuesResource.UpdateRequest.ValueInputOptionEnum.USERENTERED;
addRequest.Execute();
This example will help you to achieve what you are trying to do:
// Define request parameters.
// The ID of the spreadsheet to update.
string spreadsheetId = "YOUR-SPREADSHEET-ID"; // TODO: Update placeholder value.
// How the input data should be interpreted.
string valueInputOption = "RAW"; // TODO: Update placeholder value. Ex -> RAW
// The new values to apply to the spreadsheet.
List<ValueRange> data = new List<ValueRange>(); // Instanciate a list of type ValueRange
ValueRange values = new ValueRange(); // Instanciate a ValueRange object
values.Range = "A1:B2"; // The range you want to update
// Depending in your number of rows, create some logic to populate them
List<object> firstRow = new List<object> { "Hello", 2};
List<object> secondRow = new List<object> { 3, "Hey!"};
// Populate the values to be inserted in the sheet
values.Values = new List<IList<object>> { firstRow, secondRow };
// add values to the data ValueRange List
data.Add(values);
// TODO: Assign values to desired properties of `requestBody`:
BatchUpdateValuesRequest requestBody = new BatchUpdateValuesRequest();
requestBody.ValueInputOption = valueInputOption;
requestBody.IncludeValuesInResponse = true;
requestBody.Data = data;
// Build and make the request
SpreadsheetsResource.ValuesResource.BatchUpdateRequest request
= service.Spreadsheets.Values.BatchUpdate(requestBody, spreadsheetId);
BatchUpdateValuesResponse response = request.Execute();
IList<IList<object>> updatedValues = response.Responses[0].UpdatedData.Values;
// Print updated values
Console.WriteLine("These are the updated values");
foreach (var row in updatedValues)
{
Console.WriteLine("{0}, {1}", row[0], row[1]);
}
Console.Read();
Following the Method: spreadsheets.values.batchUpdate endpoint documentation and the Try this API, I was able to get an idea on how to build the request update body.
Notice I created a List<ValueRange>, which I populate with the appropriate data and in that way make the request.
Documentation
For more info, you can check:
.NET Quickstart
Google Sheets API .NET reference documentation
Related
I'm trying to modify the row height in Google sheets of a row I just added. The row consists of a list of strings (i.e. cells). First I add the row, then I try to modify the height:
// I need to convert my list of strings into a list of objects
// there's probably a better way to do this...
var valueRange = new ValueRange();
var oblist = new List<object>();
foreach (var thing in columns)
{
oblist.Add(thing);
}
valueRange.Values = new List<IList<object>>() { oblist };
var appendRequest = service.Spreadsheets.Values.Update(valueRange, spreadsheetId, $"{sheetname}!A{rownumber}:Z{rownumber}");
appendRequest.ValueInputOption = SpreadsheetsResource.ValuesResource.UpdateRequest.ValueInputOptionEnum.USERENTERED;
var appendResponse = appendRequest.Execute();
// now change the row height to 100 pixels.
BatchUpdateSpreadsheetRequest r = new BatchUpdateSpreadsheetRequest();
UpdateDimensionPropertiesRequest request = new UpdateDimensionPropertiesRequest());
request.Range = new DimensionRange();
request.Range.SheetId = sheetId;
request.Range.Dimension = "ROWS";
request.Range.StartIndex =
request.Range.EndIndex = rownumber;
request.Properties = new DimensionProperties();
request.Properties.PixelSize = 100;
request.Fields = "pixelSize";
r.Requests.Add(request);
var bu = service.Spreadsheets.BatchUpdate(r, spreadsheetId);
bu.Execute();
The problem is in the third-last line where I can't add request to the Requests list, as request is not derived from the Request class.
Instead of trying to add the request directly to the batch, I need to add a Requests list to the batch, and then add the request to the Requests list:
UpdateDimensionPropertiesRequest request = new UpdateDimensionPropertiesRequest();
request.Range = new DimensionRange();
request.Range.SheetId = sheetId;
request.Range.Dimension = "ROWS";
request.Range.StartIndex = firstrow;
request.Properties = new DimensionProperties();
request.Properties.PixelSize = 100;
request.Fields = "pixelSize";
// now add the request to the batch
BatchUpdateSpreadsheetRequest busr = new BatchUpdateSpreadsheetRequest();
busr.Requests = new List<Request>();
busr.Requests.Add(new Request { UpdateDimensionProperties = request });
var bur = service.Spreadsheets.BatchUpdate(busr, spreadsheetId);
bur.Execute();
So I'm trying to scrape some website data (specifically the first table here). I am using the table xpath, and trying to get the specific row data assigned to my model.
public static async Task<List<SuspensionModel>> GetSuspensionData()
{
var htmlDocument = new HtmlDocument();
var httpResponseMessage = await _httpClient.GetAsync(_2020SuspUrl);
await EnsureSuccessStatusCode(httpResponseMessage);
var SuspStatsAsHtml = await httpResponseMessage.Content.ReadAsStringAsync();
htmlDocument.LoadHtml(SuspStatsAsHtml);
var suspData = ParseTable(htmlDocument, "/html/body/div[3]/div[3]/div[5]/div[1]/table[1]/tbody/tr");
//return ;
}
private static List<SuspensionModel> ParseTable(HtmlDocument htmlDocument, string xPath)
{
var returnData = new List<SuspensionModel>();
foreach (HtmlNode row in htmlDocument.DocumentNode.SelectNodes(xPath))
{
HtmlNodeCollection cells = row.SelectNodes("td");
var arr = new String[7];
for (int i = 0; i < cells.Count; ++i)
{
arr[i] = cells[i].InnerText;
}
var susp = new SuspensionModel
{
IncidentDate = DateTime.Parse(arr[0]),
OffenderName = arr[1],
OffenderTeam = arr[2],
OffenseDesc = arr[3],
ActionDate = DateTime.Parse(arr[4]),
OffenseLength = arr[5],
SalaryLoss = int.Parse(arr[6])
};
returnData.Add(susp);
}
return returnData;
}
In my ParseTable method, where I am assigning values in my model, how can I access the specific cell data in the given row? Basically, I want to do something like:
foreach row, step through each cell and assign to the correct model value. As I have it now, my cells variable always returns null, so I assume I am not using HtmlAgilityPack correctly.
Any assistance is appreciated here!
I ended up resolving this. I was missing two things, and it turns out it wasn't related to HtmlAgilityPack.
I needed to add .Skip(1) to my foreach row so that it skipped the table header row.
foreach (HtmlNode row in htmlDocument.DocumentNode.SelectNodes(xPath).Skip(1))
I needed to fix my SalaryLoss value. I was assigning it as an int, but I needed to change that to a double as it was a currency value.
SalaryLoss = double.Parse(arr[6], System.Globalization.NumberStyles.Currency)
I am junior developer and I am trying to populate an ArrayList from a Dictionary. My problem is rather then adding a new record to the ArrayList it adds the new record but also overwrites the values for all the other values in the array.
So if I inspect the values as the ArrayList is being populated I see the values from the Dictionary as expected. But when that row is inserted into the ArrayList all of the existing rows are over written with the data from current Dictionary Row. So I end up with an ArrayList with several rows that are a duplicate of the last record added from the dictionary. My code is shown below. Can someone please tell me what am I doing wrong? Code below
ArrayList arrData = new ArrayList();
eSummary edata = new eSummary();
//Starts with the first 50 recods retrieved and adds them to the ArrayList. Loops thru to get remaining records
while (blnEmpty)
{
if (response.IsSuccessStatusCode)
{
string json = response.Content.ReadAsStringAsync().Result;
var jss = new JavaScriptSerializer();
var dict = jss.Deserialize<Dictionary<string, dynamic>>(json);
for (int i = 0; i < dict.Values.Sum(x => x.Count); i++)
{
foreach (var item in dict)
{
string checkId = (dict["data"][i]["Id"]);
edata.Id = dict["data"][i]["Id"];
edata.idExternal = (dict["data"][i]["idExternal"]) == null ? "" : (dict["data"][i]["idExternal"]);
edata.Type = "Video";
edata.ownerId = (dict["data"][i]["uploadedByOwnerId"]);
edata.dateUploaded = Convert.ToDateTime((dict["data"][i]["dateUploaded"]));
edata.durationSeconds = Convert.ToDouble((dict["data"][i]["durationSeconds"]));
edata.category = (dict["data"][i]["categories"]).Count < 1 ? string.Empty : (dict["data"][i]["categories"][0]);
edata.title = (dict["data"][i]["title"]) == string.Empty ? string.Empty : (dict["data"][i]["title"]);
edata.dateRecordStarted = Convert.ToDateTime((dict["data"][i]["dateRecordStart"]));
edata.DateAPIRan = DateTime.Now;
if (CheckAutoTag(checkId, dict["data"][i]["tags"]))
{
edata.AutoTagged = true;
}
else edata.AutoTagged = false;
arrData.Add(edata);
edata is a reference type. You keep updating the values of a single object within the loop.
You need to call new eSummary() and set the values on the new object and then add that to your list.
But do note, you should not be using ArrayList in modern c#. Use a List<eSummary> instead.
I am using the below API and method to try and get all PR commits that merge a given commitId. But the API only returns a max of 250. Is there a parameter or pagination technique to get the remaining?
public void GetAllPullRequestsForCommit(Guid repoId, string commitId)
{
var query = new GitPullRequestQuery();
var input = new GitPullRequestQueryInput() { Type = GitPullRequestQueryType.Commit, Items = new List<string>() { commitId } };
query.QueryInputs = new List<GitPullRequestQueryInput>() { input };
var response = _gitClient.GetPullRequestQueryAsync(query, repoId).Result;
}
Using the Amazon Product Advertising API I am searching for 2 different UPCs:
// prepare the first ItemSearchRequest
// prepare a second ItemSearchRequest
ItemSearchRequest request1 = new ItemSearchRequest();
request1.SearchIndex = "All";
//request1.Keywords = table.Rows[i].ItemArray[0].ToString();
request1.Keywords="9120031340270";
request1.ItemPage = "1";
request1.ResponseGroup = new string[] { "OfferSummary" };
ItemSearchRequest request2 = new ItemSearchRequest();
request2.SearchIndex = "All";
//request2.Keywords = table.Rows[i+1].ItemArray[0].ToString();
request2.Keywords = "9120031340300";
request2.ItemPage = "1";
request2.ResponseGroup = new string[] { "OfferSummary" };
// batch the two requests together
ItemSearch itemSearch = new ItemSearch();
itemSearch.Request = new ItemSearchRequest[] { request1,request2 };
itemSearch.AWSAccessKeyId = accessKeyId;
// issue the ItemSearch request
ItemSearchResponse response = client.ItemSearch(itemSearch);
foreach (var item in response.Items[0].Item)
{
}
foreach (var item in response.Items[1].Item)
{
}
Is it possible to combine these two separate requests into one request and just have the first request return 2 items by setting keywords = "9120031340256 and 9120031340270"
Does anyone know how to do this?
Do I need to specifically search the UPC?
From looking at the API docs I think you may want to use an ItemLookup if you want to get results for multiple UPCs.
ItemLookup itemLookup = new ItemLookup(){
AssociateTag = "myaffiliatetag-20"
};
itemLookup.AWSAccessKeyId = MY_AWS_ID;
ItemLookupRequest itemLookupRequest = new ItemLookupRequest();
itemLookupRequest.IdTypeSpecified = true;
itemLookupRequest.IdType = ItemLookupRequestIdType.UPC;
itemLookupRequest.ItemId = new String[] { "9120031340300", "9120031340270" };
itemLookupRequest.ResponseGroup = new String[] { "OfferSummary" };
itemLookup.Request = new ItemLookupRequest[] { itemLookupRequest };
ItemLookupResponse response = client.ItemLookup(itemLookup);
foreach(var item in response.Items[0])
{
//Do something...
Console.WriteLine(item.ItemAttributes.Title);
}
That being said, if you are not working with lookups by some ID (UPC, ASIN, etc) your original code of doing batched keyword searches appears to be only way to make multiple keyword searches in a single request (that I could find..). If doing keyword searches you could always make a ItemSearchRequest generator method to cut down on duplicate code when creating multiples.
You can use the following nuget
package.
PM> Install-Package Nager.AmazonProductAdvertising
Example
var authentication = new AmazonAuthentication("accesskey", "secretkey");
var client = new AmazonProductAdvertisingClient(authentication, AmazonEndpoint.US);
var result = await client.GetItemsAsync(new string[] { "B00BYPW00I", "B004MKNBJG" });