Expand rows based on the integer values of a column while parsing through the values in remainder columns to separate values among the inserted rows - postgresql

What I need is to insert rows according to the integer value in a column while parsing through the values in the remaining columns to separate their values on the new inserted rows.
I have a table like this
ID
Household
User Count
Show 1
Show 2
Show 3
Show 4
123
House 1
2
Shooter
Dark
1234
House 2
4
Awake
Arrow
Lou
Ozark
And I need an expanded table where each row represents an individual user
ID
Household
User Count
Show 1
Show 2
Show 3
Show 4
123
House 1
1
Shooter
123
House 1
1
Dark
1234
House 2
1
Awake
1234
House 2
1
Arrow
1234
House 2
1
Lou
1234
House 2
1
Ozark
I need to solve this problem using either Google Apps Script or PostgreSQL.

In your situation, when Google Apps Script is used, how about the following sample script?
Sample script:
Please copy and paste the following script to the script editor of Spreadsheet and save the script. And, please set the source and destination sheet names.
function myFunction() {
const srcSheetName = "Sheet1"; // Please set source sheet name.
const dstSheetName = "Sheet2"; // Please set source sheet name.
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName(srcSheetName);
const [header, ...values] = sheet.getDataRange().getValues();
const res = [header, ...values.flatMap(([a, b, c, ...d]) => {
const len = d.length;
return [...Array(c)].map((_, i) => {
const temp = [...Array(i).fill(null), d[i]];
return [a, b, 1, ...temp, ...Array(len - temp.length).fill(null)];
});
})];
ss.getSheetByName(dstSheetName).getRange(1, 1, res.length, res[0].length).setValues(res);
}
When this script is run, the values are retrieved from source sheet, and the values are converted, and then, the converted values are put to the destination sheet. In this case, when your sample input table is used, the sample output table can be obtained.
If you want to use this script as a custom function, how about the following sample script? When your showing input table is used, please put a custom function like =SAMPLE(A1:G3) to a cell. By this, the result values are returned.
function SAMPLE(v) {
const [header, ...values] = v;
return [header, ...values.flatMap(([a, b, c, ...d]) => {
const len = d.length;
return [...Array(c)].map((_, i) => {
const temp = [...Array(i).fill(null), d[i]];
return [a, b, 1, ...temp, ...Array(len - temp.length).fill(null)];
});
})];
}
Note:
This sample script is prepared from your sample input and output tables. So, when you changed the table or your actual Spreadsheet is different from your sample input table, the script might not be able to be used. Please be careful about this.
Reference:
map()

Related

Google script - send email alert

I have a script that looks into values in column G and if the correspondent cell in column A is empty, sends me an email.
--- WHAT WORKS --
It works ok for static values: it sends one email per each not empty cell in column G for which there is no value in column A
--- WHAT DOESN'T WORK --
It sends several emails for what I assume it's every Column G cell (empty or not) when the column A values are fetched from another tab. That way it's like all G and A cells have data, so I get multiple unwanted emails.
This is the script code:
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet to send emails');
const data = sh.getRange('A2:G'+sh.getLastRow()).getValues();
data.forEach(r=>{
let overdueValue = r[0];
if (overdueValue === ""){
let name = r[6];
let message = 'Text ' + name;
let subject = 'TEXT.'
MailApp.sendEmail('myemail#gmail.com', subject, message);
}
});
}
And this is the link to the test sheet:
https://docs.google.com/spreadsheets/d/1OKQlm0PjEjDB7PXvt34Og2fa4vPZWnvLazTEawEtOXg/edit?usp=sharing
In this test case, I "should" only get one email, related to ID 55555. With the script as is, I get one related to 55555 and several others "undefined".
To avoid e-mail spam, I didn't add the script to that sheet but it shows the "Vlookup" idea.
Can anyone give me a hand, please?
Thank you in advance
Issue:
The issue with your original script is that the sh.getLastRow returns 1000 (it also processes those rows that doesn't have contents, result to undefined)
Fix 1: Get specific last row of column G:
const gValues = sh.getRange('G1:G').getValues();
const gLastRow = gValues.filter(String).length;
or
Fix 2: Filter data
const data = sh.getRange('A2:G' + sh.getLastRow()).getValues().filter(r => r[6]);
Note:
As Kris mentioned in the comments, there is a specific case where getting the last row above will fail (same with getNextDataCell). This will not properly get the last row WHEN there are blank rows in between the first and last row of the column. If you have this kind of data, then use the 2nd method which is filtering the data.
If your data in column G does not have blank cells in between the first and last row, then any method should work.
I checked your test sheet, and sh.getLastRow() is 1000.
OPTION 1
If column G won't have empty cells between filled ones, then you can do this:
const ss = SpreadsheetApp.getActive();
const sheet = ss.getSheetByName("Sheet to send emails");
// get the first cell in column G
var gHeader = sheet.getRange(1, 7);
// equivelent of using CTRL + down arrow to find the last da
var lastRow = gcell.getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
const data = sheet.getRange(2, 1, lastRow, 7).getValues();
OPTION 2
Add another condition to your code - like this:
data.forEach(r=>{
let overdueValue = r[0];
let name = r[6]
// check if the value in col A is blankd and col G is not blank
if (overdueValue === "" && name !== ""){
let message = 'Text ' + name;
let subject = 'TEXT.'
MailApp.sendEmail('myemail#gmail.com', subject, message);
}
});
And to speed it up, use a named range to limit how many rows it has to iterate through:
const ss = SpreadsheetApp.getActive();
const data = ss.getRangeByName("Your_NamedRange_Here").getValues();

Exporting output results from a model into the input of a different model

I'm trying to build a model of a factory using the personal learning edition of AnyLogic. Since this version has a limited number of blocks per model, building the full factory on a single model is presenting itself as an impossible task. In order to surpass this issue I want to split the factorys main processes into different models, which means I'll have to feed the output of process A into the input of process B.
My question is: how can I export a time stamped output of a model into the input of a different model?
Thank you in advance.
You have 2 options
Option 1: Through an Excel file (or txt file)
Simply link an Excel file in your model, using the object from the connectivity palette
Then you can get the data using code similar to below
int excelRow = 2;
String sheetName = "Sheet1!";
String cellName = sheetName + "A" + excelRow;
while (excelFile.cellExists( cellName )) {
int x = (int)excelFile.getCellNumericValue( sheetName + "A" + excelRow);
int b = (int)excelFile.getCellNumericValue( sheetName + "B" + excelRow);
int c = (int)excelFile.getCellNumericValue( sheetName + "C" + excelRow);
boolean d = excelFile.getCellBooleanValue( sheetName + "D" + excelRow);
excelRow ++; // Increase the row that we will lookup in the Excel
}
Just a while loop where you go from one excel line to the next as long as the line exists, and then do what ever is needed with the data
Option 2: AnyLogic Internal DB
Simply import your excel sheet to the AnyLogic DB and then loop over the entries in the table using a for loop
List<Tuple> rows = selectFrom(db_table).list();
for (Tuple row : rows) {
traceln(
row.get( db_table.db_column )
);
}

Flutter: How can I copy paste column values directly into my flutter UI from an excel spreadsheet?

Is there a specific widget for this? I want to be able to open a spreadsheet on my phone (a google sheet) or an excel file, select a column containing 10-50 latitude points, and another column containing longitude points. I want to be able to paste this directly into my app and create a latlng list from it.
I've tried using Sticky Headers (below) but it will only let me paste everything into one cell at a time:
StickyHeadersTable(
columnsLength: titleColumn.length,
rowsLength: titleRow.length,
columnsTitleBuilder: (i) => Text(titleColumn[i]),
rowsTitleBuilder: (i) => Text(titleRow[i]),
contentCellBuilder: (i, j) =>
Container(height: 50, width: 50, child: TextField()),
legendCell: Text('Sticky Legend'),
),
Is there a way to modify this to accept entire columns from another spreadsheet via copy/paste?
Understanding how copy/paste works in Spreadsheets
Assume there is data something like this in Spreadsheet, or MS Excel
A1 B1 C1
A2 B2 C2
When you copy this data, it will be copied as a string in following format
A1\tB1\tC1\nA2\tB2\tC2
To put this data in your table
first split them into rows
and then into Cells
Example -
void main() {
String data = "A1\tB1\tC1\nA2\tB2\tC2";
List<String> rows = data.split('\n');
List cells = <List<String>>[];
for (String row in rows) {
cells.addAll(row.split('\t'));
}
print(cells);
//prints: [[A1, B1, C1], [A2, B2, C2]]
}
NOTE: If you copy only one column, each item will be separated with a '\n'(New Line).
How to use solution with Flutter
Note that spreadsheets doesn't allow you to use new lines in a single cell. So when user copied a text into a cell or use \n then you can handle the data with a function and convert all data into a list as mentioned above.

Get values from sap.m.Table

Is it possible to get the values from a sap.m.Table without clicking a specific entry?
With an event I can get the values by the actual context but what I need is to get the whole items with the specific characteristic.
For example my table has the following columns (column D is not invisible):
A B C D
with the entries shown below:
A B C D
1 2 3 4
4 b 2 1
What I need now is the first row for example:
1 2 3 4
I want to write something like
table.getItem("A")[0]
to get 1 as a result.
How can I achieve this?
You can get all the Items in the table using getItems(), which will give you an Array of Items. You can then get the bindingContext for any of the Items.
var iRowIndex = 0; //For First row in the table
var oTable = this.getView.byId("myTable"),
oModel = oTable.getModel(),
aItems = oTable.getItems();
if(iRowIndex < aItems.length){
oModel.getProperty("ColA",aItems[iRowIndex].getBindingContext());
}

Power Query - remove characters from number values

I have a table field where the data contains our memberID numbers followed by character or character + number strings
For example:
My Data
1234567Z1
2345T10
222222T10Z1
111
111A
Should Become
123456
12345
222222
111
111
I want to get just the member number (as shown in Should Become above). I.E. all the digits that are LEFT of the first character.
As the length of the member number can be different for each person (the first 1 to 7 digit) and the letters used can be different (a to z, 0 to 8 characters long), I don't think I can SPLIT the field.
Right now, in Power Query, I do 27 search and replace commands to clean this data (e.g. find T10 replace with nothing, find T20 replace with nothing, etc)
Can anyone suggest a better way to achieve this?
I did successfully create a formula for this in Excel...but I am now trying to do this in Power Query and I don't know how to convert the formula - nor am I sure this is the most efficient solution.
=iferror(value(left([MEMBERID],7)),
iferror(value(left([MEMBERID],6)),
iferror(value(left([MEMBERID],5)),
iferror(value(left([MEMBERID],4)),
iferror(value(left([MEMBERID],3)),0)
)
)
)
)
Thanks
There are likely several ways to do this. Here's one way:
Create a query Letters:
let
Source = { "a" .. "z" } & { "A" .. "Z" }
in
Source
Create a query GetFirstLetterIndex:
let
Source = (text) => let
// For each letter find out where it shows up in the text. If it doesn't show up, we will have a -1 in the list. Make that positive so that we return the index of the first letter which shows up.
firstLetterIndex = List.Transform(Letters, each let pos = Text.PositionOf(text, _), correctedPos = if pos < 0 then Text.Length(text) else pos in correctedPos),
minimumIndex = List.Min(firstLetterIndex)
in minimumIndex
in
Source
In the table containing your data, add a custom column with this formula:
Text.Range([ColumnWithData], 0, GetFirstLetterIndex([ColumnWithData]))
That formula will take everything from your data text until the first letter.