Google Sheets API v4 is not passing null values as part of a ValueRange.
When a ValueRange is created with the following values:
"Test A", "Test B", null, null, "Test E"
with the range:
"A1:E1"
I get the following result:
A B C D E
1 Test A Test B Test E
But the expected result is:
A B C D E
1 Test A Test B Test E
The API used is spreadsheets().values().update(ID, range, ValueRange)
One possible solution is setting ValueInputOption to "USER_ENTERED" if not done already, however the problem still persists.
Here is a SSCCE in Java:
public static void test(Sheets service, String id) {
String range = "A1:E1";
List<List<Object>> values = Arrays.asList(Arrays.asList("Test A", "Test B", null, null, "Test E"));
ValueRange vRange = new ValueRange();
vRange.setRange(range);
vRange.setValues(values);
try {
System.out.println(service.spreadsheets().values().update(id, range, vRange)
.setValueInputOption("USER_ENTERED").execute().toPrettyString());
} catch (IOException e) {
e.printStackTrace();
}
}
And the result:
{
"spreadsheetId" : "[id]",
"updatedCells" : 3,
"updatedColumns" : 3,
"updatedRange" : "Sheet1!A1:C1",
"updatedRows" : 1
}
What changes need to be made to get null recognized, so that E will end up in the E column instead of the null values being glanced over?
I ran through a similar problem.
You can use Data.NULL_STRING (from com.google.api.client.util) instead of a native java null.
Fixed it for me
Related
When I try to find the size of all the tables using listTables API of BigQuery java client, it returns null. But if I use getTable individually, I get the proper data. Is this a known issue, or am I doing something wrong. Following is the code that returns null value for numBytes:
Page<Dataset> datasetPage = getAllDatasets("projectId");
if(datasetPage!=null) {
for (Dataset dataset : datasetPage.iterateAll()) {
for(Table table : dataset.list().iterateAll()) {
System.out.println(table.getNumBytes()); // Returns Null. **
}
}
}
In this Public Issue Tracker thread, it has been discussed that getting null value for numBytes and numRows using listTables is the expected behaviour. The BigQuery API considers retrieving numBytes and numRows to be an expensive operation and thus returns null. So, the listTables only returns partial information on a table.
As a workaround, use getTable() to retrieve the information of the table individually in a loop. I tested the below code snippet and was able to get the table size in bytes for all the tables.
public static void getAllTableSize(String projectId) {
try {
BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();
Page<Dataset> datasetPage = bigquery.listDatasets(projectId);
if(datasetPage!=null) {
for (Dataset datasetTemp : datasetPage.iterateAll()) {
for(Table table : datasetTemp.list().iterateAll()) {
Table tableTemp = bigquery.getTable(table.getTableId());
String tableName = tableTemp.getTableId().getTable();
Long tableSize = tableTemp.getNumBytes();
System.out.println("Table Name: " + tableName + " " + "Table Size: " + tableSize);
}
}
}
} catch (BigQueryException e) {
System.out.println("Error occurred: " + e.toString());
}
}
To answer my own question listTables api is designed to return only the partial information. This is mentioned in the code document
https://github.com/googleapis/java-bigquery/blob/dfa15e5ca08a3227f015a389c4c08732178a73e7/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/spi/v2/BigQueryRpc.java#L155
optaplanner-bom 7.59.0.Final. In my PlanningEntity class Task there is a PlanningVariable and a CustomShadowVariable
#PlanningVariable(valueRangeProviderRefs = "indexRange")
private Index index;
#CustomShadowVariable(variableListenerClass = UpdatingVariableListener.class,
sources = { #PlanningVariableReference(variableName = "index") })
private Long d;
in the PlanningSolution class the range is referred:
#ProblemFactCollectionProperty
#ValueRangeProvider(id = "indexRange")
private List<Index> indexList;
the rule file is to minimize the sum of all "d"s:
rule
when
accumulate(
Task(index != null, $d: d);
$s: sum($d)
)
then
scoreHolder.addSoftConstraintMatch(kcontext, 1, (int)(-$s));
end
in the afterVariableChanged() of the UpdatingVariableListener, by calling scoreDirector.getWorkingSolution(), I can see in the variable "indexList" there are two elements (let's call them "1" and "2") and none of them is java "null". When I set breakpoint in the afterVariableChanged(), with the first hit the "index" is "2", the second time it's "1", the third time is java "null". And noticed that for the second time and third time, the solution object are the same object. Do not think "null" should be set as it's not in the range. Anything wrong was done?
Hi i am working on a Migration project from Spring to Mule .
In Java we have small function like
private String[] getPurpose(loanPurpose){
String purpose[] = new String[2];
if ("REFINANCE".equalsIgnoreCase(loanPurpose)) {
purpose[0] = "Refinance";
purpose[1] = "Cash-Out";
return purpose;
}
return null;
}
In Mule i am writing it like below .
fun getPurpose(data) =
if(upper("PURCHASE") == data)
// how i can assign the values in string array and return
[ "Refinance"," Cash-out"]
Just create the array literal with the strings as the last value of the function. I'n this case the is the value of the true branch of if.
It should work fine in studio as well. Probably the way the if value is represented could be throwing it off.. Try with the following:
%dw 2.0
output application/json
fun getPurpose(data) =
if(upper("PURCHASE") == data) (["Refinance", "Cash-Out"]) else if (1 == 2) "abc" else "nothing"
---
getPurpose("PURCHASE")
Output:
[
"Refinance",
"Cash-Out"
]
I am collecting responses to an online survey form in a table like this:
CREATE TABLE [Survey]
(
ID int IDENTITY(1,1) NOT NULL,
UserName varchar(50) NOT NULL,
Responses varchar(max) NOT NULL,
Taken datetime NOT NULL
)
When the user clicks the submit button, a process grabs all the checkboxes that were clicked and concatenates their names into a delimited string, and stuffs that into the table along with the other fields. Essentially same as:
INSERT INTO [Survey] (UserName, Responses, Taken) VALUES ('John', 'chkSize', GetDate())
INSERT INTO [Survey] (UserName, Responses, Taken) VALUES ('Mary', 'chkSquare;chkSoft', GetDate())
INSERT INTO [Survey] (UserName, Responses, Taken) VALUES ('Steve', 'chkSize;chkYellow;chkRound', GetDate())
INSERT INTO [Survey] (UserName, Responses, Taken) VALUES ('April', 'chkRound;chkStacked;chkFiltered;chkBrown', GetDate())
Is there a way to easily go through all the "Responses" for the whole table, find all possible values, and then return them as a Unique list in their own table? i.e.:
chkBrown
chkFiltered
chkRound
chkSize
chkSoft
chkSquare
chkStacked
chkYellow
You can do what you want using string_split():
select s.value, count(*)
from survey su cross apply
string_split(su.responses, ';') s
group by s.value;
Here is a db<>fiddle.
The fact that you can do this does not mean that you should. You should store the responses in a separate table, with one row per response.
If this is just a simple one page, check box only survey, one approach is
// declare flags enum
[Flags]
public enum Checkboxes : int
{
none = 0,
chkBrown = 1,
chkFiltered = 2,
chkRound = 4,
chkSize = 8,
chkSoft = 16,
chkSquare = 32,
chkStacked = 64,
chkYellow = 128
}
// on initialize/constructor add these values to your checkbox tag
chkBrown.Tag = Checkboxes.chkBrown ;
// Add checkbox extension
public shared Checkboxes GetCode(this Checkbox cb)
{
if (cb.Checked)
return (Checkboxes)cb.Tag;
return Checkboxes.none;
}
// your db value would be
Checkboxes val = chkBrown.GetCode() | chkFiltered() . . . // list all c-boxes here
// make db field integer and save this value:
(int)val
But... again. This is only good if no changes will be required and the system is static. This seem to be homework and no long term issue. But in such cases, long term scenario is many-to-many table, where you can have multiple records for same question posted as separate record. This way, SQL search is easy
Here is working fiddle where you can also see how to set your checkbox to a value retrieved from the number
using System;
public class ClsVal// instead of checkbox
{
public bool A {get; set;}
public Checkboxes C {get; set;}
}
public static class ClsValExt
{
public static Checkboxes GetCode(this ClsVal cb)
{
if (cb.A)
return (Checkboxes)cb.C;
return Checkboxes.none;
}
}
[Flags]
public enum Checkboxes : int
{
none = 0,
chkBrown = 1,
chkFiltered = 2,
chkRound = 4,
chkSize = 8,
chkSoft = 16,
chkSquare = 32,
chkStacked = 64,
chkYellow = 128
}
public class Program
{
public static void Main()
{
var c1 = new ClsVal() {A = true, C = Checkboxes.chkBrown};
var c2 = new ClsVal() {A = true, C = Checkboxes.chkFiltered};
var c3 = new ClsVal() {A = false, C = Checkboxes.chkRound};
var c4 = new ClsVal() {A = true, C = Checkboxes.chkSize};
var x = c2.GetCode() | c1.GetCode() | c3.GetCode() | c4.GetCode();
var i = (int)x;
Console.WriteLine(i);
Console.WriteLine((x & Checkboxes.chkBrown) == Checkboxes.chkBrown); //Yes
Console.WriteLine((x & Checkboxes.chkBrown) == Checkboxes.chkYellow); // No
}
}
Given a Generic List of objects that contain a member variable that is a string, what is the best way to get the object that contains the string with the longest length?
ie.
assuming val1 is the string I'm comparing:
0 : { val1 = "a" }
1 : { val1 = "aa" }
2 : { val1 = "aba" }
3 : { val1 = "c" }
what needs to be returned is object 2 because "aba" has the greatest length.
Sorry, I'll try again. You can use the following aggregation:
Dim result = elements.Aggregate(Function(a, b) If(a.val1.Length > b.val1.Length, a, b))
You could also use an order-by:
var x = myStringArray.OrderBy(s => s.Length).Last();
Dim longestLength = elements.Max(Function(el) el.val1.Length)
Dim longest = elements.First(Function(el) el.val1.Length = longestLength)