Getting value from cells horizontally - phpexcel

Hi, I have an excel sheet like the one posted above. I am trying to retrieve data from this spreadsheet and insert it into a database. An example of a few entries would be,
[personnel_no: 35, name: John, Day: 01, Value: N],
[personnel_no: 35, name: John, Day: 02, Value: N],
[personnel_no: 35, name: John, Day: 03, Value: O]
I know how to create a loop that will go through the spreadsheet by rowss but i'm stumped as to how to do it by column. I've read that phpexcel has a column iterator function but im not even sure how to do that.

Unsure why you even need the column iterator for this, because all your data is tabulated by row....
$worksheet = $objPHPExcel->getActiveSheet();
foreach ($worksheet->getRowIterator() as $row) {
$rowData = $worksheet->toArray('A'.$row->getRowIndex().':AG'.$row->getRowIndex());
... var_dump($rowData);
... insert data from $rowData into the database
}
If you want to read more about iterators, take a look at 28iterator.php in /Examples

Related

Kibana - Splitting series by field names

I was hoping to find a way to split a series by field names (and not values of a particular field) in kibana
I have a data set that looks like below:
{ { date: 24/06/2021, foo: 12, bar: 20}, { date: 24/06/2021, foo: 16, bar: 20}, { date: 25/06/2021, foo: 16, bar: 20}, { date: 25/06/2021, foo: 16, bar: 20} }
I was hoping to see something like this:
Date on the x-axis and
the average of 'foo' for that date as one point and average of 'bar' as another point on a timeseries line chart. (essentially having field values of the same document as different series(es))
Is this possible?
Context: I am importing the document from a csv and the field names ('foo' and 'bar') are columns in the csv. I have managed to get what I need by adding a 'type' column on the csv and setting its values to be 'foo' and 'bar'
example:
{ { date: 24/06/2021, val: 12, type: foo}, { date: 24/06/2021, val: 20, type: bar} ... }
and splitting the series by the 'type' field, but I wanted to know if there was a way to create the chart without having to edit the csv.
I got this to work using Kibana Lens visualization. It allows me to set Y-axis with different fields from the same document

Can't scan on DynamoDB map nested attributes

I'm new to DynamoDB and I'm trying to query a table from javascript using the Dynamoose library. I have a table with a primary partition key of type String called "id" which is basically a long string with a user id. I have a second column in the table called "attributes" which is a DynamoDB map and is used to store arbitrary user attributes (I can't change the schema as this is how a predefined persistence adapter works and I'm stuck working with it for convenience).
This is an example of a record in the table:
Item{2}
attributes Map{2}
10 Number: 2
11 Number: 4
12 Number: 6
13 Number: 8
id String: YVVVNIL5CB5WXITFTV3JFUBO2IP2C33BY
The numeric fields, such as the "12" field, in the Map can be interpreted as "week10", "week11","week12" and "week13" and the numeric values 2,4,6 and 8 are the number of times the application was launched that week.
What I need to do is get all user ids of the records that have more than 4 launches in a specific week (eg week 12) and I also need to get the list of user ids with a sum of 20 launches in a range of four weeks (eg. from week 10 to 13).
With Dynamoose I have to use the following model:
dynamoose.model(
DYNAMO_DB_TABLE_NAME,
{id: String, attributes: Map},
{useDocumentTypes: true, saveUnknown: true}
);
(to match the table structure generated by the persistence adapter I'm using).
I assume I will need to do DynamoDB "scan" to achieve this rather than a "query" and I tried this to get started and get a records where week 12 equals 6 to no avail (I get an empty set as result):
const filter = {
FilterExpression: 'contains(#attributes, :val)',
ExpressionAttributeNames: {
'#attributes': 'attributes',
},
ExpressionAttributeValues: {
':val': {'12': 6},
},
};
model.scan(filter).all().exec(function (err, result, lastKey) {
console.log('query result: '+ JSON.stringify(result));
});
If you don't know Dynamoose but can help with solving this via the AWS SDK tu run a DynamoDB scan directly that might also be helpful for me.
Thanks!!
Try the following.
const filter = {
FilterExpression: '#attributes.#12 = :val',
ExpressionAttributeNames: {
'#attributes': 'attributes',
'#12': '12'
},
ExpressionAttributeValues: {
':val': 6,
},
};
Sounds like what you are really trying to do is filter the items where attributes.12 = 6. Which is what the query above will do.
Contains can't be used for objects or arrays.

All worksheets in spreadsheet appear to be a reference to sheet 0

I am writing a price import script which reads from an Excel spreadsheet.
The spreadsheet is generated using Office 365 Excel however I am using LibreOffice Calc on Ubuntu 18.04 to view it during development - no issues here.
I'm using phpoffice/phpspreadsheet at version 1.10.1:
"name": "phpoffice/phpspreadsheet",
"version": "1.10.1",
"source": {
"type": "git",
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
"reference": "1648dc9ebef6ebe0c5a172e16cf66732918416e0"
},
I am trying to convert the data of each worksheet within the spreadsheet to an array.
There are 3 worksheets, each representing 'Zones' - Zone 1, Zone 2 and Zone 3.
I appear to be getting the same data for Zone 2 and Zone 3 as Zone 1 - the worksheet title is correctly returned however the data is not changing between worksheets.
/**
* #param Spreadsheet $spreadsheet
*
* #return array
*/
private function parseZones(Spreadsheet $spreadsheet): array
{
$zones = [];
foreach ([0, 1, 2] as $sheetIndex) {
$sheet = $spreadsheet->getSheet($sheetIndex);
// this is correctly reporting 'Zone 1', 'Zone 2' and 'Zone 3' - sheet title is accurate
$sheetName = $sheet->getTitle();
// sheet 0 is accurate
$sheetData = $sheet->toArray();
// on sheet index 1 and 2 - $sheetData is identical to that of sheet index 0
// the XLSX file in OpenOffice / Excel has distinctly different row data - 50% less rows in both cases
// feels like a memory cache issue / some mis-referencing?
}
// retrieving rows using this approach yields the same result:
foreach ($spreadsheet->getAllSheets() as $sheet) {
// this is correctly reporting 'Zone 1', 'Zone 2' and 'Zone 3' - sheet title is accurate
$sheetName = $sheet->getTitle();
// on sheet index 1 and 2 - $sheetData is identical to that of sheet index 0
$sheetData = $sheet->toArray();
}
return $zones;
}
Any ideas?
Thanks
I'm a numpty - completely failed to see / check the row filtering in the spreadsheet.
It's returning the correct data.
None issue, sorry!
I've since started to investigate how to read a worksheet whilst obeying the filters embedded in the spreadsheet, and it appears Worksheet::toArray() does not automatically take filters in to account - nor does iterating columns and rows manually, see:
https://phpspreadsheet.readthedocs.io/en/latest/topics/autofilters/
You must manually test a row's visibility settings, as per the docs.
Hope this helps!
Try just change current active sheet before reads.
$spreadsheet->setActiveSheetIndex($sheetIndex);
$sheet = $spreadsheet->getActiveSheet();
$dataArray = $sheet
->rangeToArray(
'A4:O07', // The worksheet range that we want to retrieve
NULL, // Value that should be returned for empty cells
TRUE, // Should formulas be calculated (the equivalent of getCalculatedValue() for each cell)
TRUE, // Should values be formatted (the equivalent of getFormattedValue() for each cell)
TRUE // Should the array be indexed by cell row and cell column
);
PhpSpreadsheet

How to get 3 data that have the highest value of a column in the table

I am using knex and bookshelf, and my table consists of author, title, content, count, and each data looks like this:
author: 'John Doe',
title: 'aaaaa',
content: 'aaaaaaaa'
count: 54,
I want to retrieve data based on the value of count, and I want to get 4 data that has the highest count value.
If I want to retrieve all data, I am doing like this:
router.get('/', (req, res) => {
Article.forge().fetchAll().then(article => {
res.json(article);
})
})
Is there any way that I can do like forge({ count: 3 data that has the highest count value }) or
What should I add the code so that I can achieve this?
Combine orderBy with fetchPage
Article
.orderBy('-count')
.fetchPage({
pageSize: 3
})
.forge()
This highlights a reason why my team is removing bookshelf and just using basic knex. Unless you are wanting to fetch related models it's simpler to deal without the ORM layer. The knex equivalent knex code is:
knex('articles')
.orderBy('count', 'desc')
.limit(3)
Which is slightly simpler and the resulting rows' properties can be accessed directly, ie rows[0].id rather than rows[0].get('id')

Reformatting date in google spreadsheet

I'm setting up a spreadsheet for someone else with a form to enter data.
One of the columns is supposed to hold a date. The input date format is like this example: "Jan 26, 2013" (there will be a lot of copy & paste involved to collect data, so changing the format at input step is not a real option).
I need this date column to be sortable, but the spreadsheet doesn't recognize this as a date but simply as a string. (It would recognize "Jan-26-2013", I've tried.)
So I need to reformat the input date.
My question is: how can I do this? I have looked around and google apps script looks like the way to go (though I haven't found a good example of reformatting yet).
Unfortunately my only programming experience is in Python, and of intermediate level. I could do this in Python without a problem, but I don't know any JavaScript.
(My Python approach would be:
splitted = date.split()
newdate = "-".join([splitted[0], splitted[1][:-1], splitted[2]])
return newdate
)
I also don't know how I'd go about linking the script to the spreadsheet - would I attach it to the cell, or the form, or where? And how? Any link to a helpful, understandable tutorial etc. on this point would help greatly.
Any help greatly appreciated!
Edit: Here's the code I ended up with:
//Function to filter unwanted " chars from date entries
function reformatDate() {
var sheet = SpreadsheetApp.getActiveSheet();
var startrow = 2;
var firstcolumn = 6;
var columnspan = 1;
var lastrow = sheet.getLastRow();
var dates = sheet.getRange(startrow, firstcolumn, lastrow, columnspan).getValues();
newdates = []
for(var i in dates){
var mydate = dates[i][0];
try
{
var newdate = mydate.replace(/"/g,'');
}
catch(err)
{
var newdate = mydate
}
newdates.push([newdate]);
}
sheet.getRange(startrow, firstcolumn, lastrow, columnspan).setValues(newdates)
}
For other confused google-script Newbies like me:
attaching the script to the spreadsheet works by creating the script from within the spreadsheet (Tools => Script Editor). Just putting the function in there is enough, you don't seem to need a function call etc.
you select the trigger of the script from the Script Editor (Resources => This Project's Triggers).
Important: the script will only work if there's an empty row at the bottom of the sheet in question!
Just an idea :
If you double click on your date string in the spreadsheet you will see that its real value that makes it a string instead of a date object is this 'Jan 26, 2013 with the ' in front of the string that I didn't add here...(The form does that to allow you to type what you want in the text area, including +322475... for example if it is a phone number, that's a known trick in spreadsheets cells) You could simply make a script that runs on form submit and that removes the ' in the cells, I guess the spreadsheet would do the rest... (I didn't test that so give it a try and consider this as a suggestion).
To remove the ' you can simply use the .replace() method **
var newValue = value.replace(/'/g,'');
here are some links to the relevant documentation : link1 link2
EDIT following your comment :
It could be simpler since the replace doesn't generate an error if no match is found. So you could make it like this :
function reformatDate() {
var sheet = SpreadsheetApp.getActiveSheet();
var dates = sheet.getRange(2, 6, sheet.getLastRow(), 1).getValues();
newdates = []
for(var i in dates){
var mydate = dates[i][0];
var newdate = mydate.replace(/"/g,'');
newdates.push([newdate]);
}
sheet.getRange(2, 6, sheet.getLastRow(), 1).setValues(newdates)
}
Also, you used the " in your code, presumably on purpose... my test showed ' instead. What made you make this choice ?
Solved it, I just had to change the comma to dot and it worked

Resources