How do I use linest function in phpspreadsheet? - php

I am using 33_Chart_create_scatter.php to generate a XY scatter chart. I am closing in on completion. All I have left is inducing the linest function. Would someone please provide some code on the use of linest in phpspreadsheet?
I've done a lot of googles, with no luck. Lots of visits to phpspreadsheet docs. With a lot of information, I don't understand. I have not used classes to this point, so I don't know how to form the code to talk with the classes shown in the code section below?
Here is the data I use:
$xAxisTickValues = [
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$C$1:$C$18', null, 18),
new DataSeriesValues(DataSeriesValues::DATASERIES_TYPE_NUMBER, 'Worksheet!$F$1:$F$18', null, 18)
[;
\PhpOffice\PhpSpreadsheet\Calculation\Statistical::LINEST
'LINEST' => [
'category' => Category::CATEGORY_STATISTICAL,
'functionCall' => [Statistical::class, 'LINEST'],
'argumentCount' => '1-4',
],
public static function LINEST($yValues, $xValues = null, $const = true, $stats = false)
{
$const = ($const === null) ? true : (bool) Functions::flattenSingleValue($const);
$stats = ($stats === null) ? false : (bool) Functions::flattenSingleValue($stats);
if ($xValues === null) {
$xValues = range(1, count(Functions::flattenArray($yValues)));
}
Of course, I have no results yet. My expectations would be to have returned the linest statistic derived.
No one has added anything for a week. Here is what I have accomplished in that week: I got the following two data arrays by running the formula wizzard / linest on the data in 33 Chart create scatter. The chart I made. So, I know what the data is that I want from phpspreadsheet/linest.
Six foot data array
0.798178535 18.35040936
0.012101577 0.241020964
0.996335545 0.53274435
4350.269442 16
1234.67843 4.541064671
Ten foot data array
0.819287926 16.98988304
0.007826008 0.15586663
0.998542214 0.344522174
10959.54502 16
1300.848983 1.899128449
setCellValue, puts the formula in cell A32 and cell A32 displays the first number from the Six foot data array above.
$helper->log, gives the following output. The getCell gives the linest formula in the cell.
getCalculatedValue gives the Last value in the Six foot data array above.
19:12:47 Write Xlsx format to 33_Chart_create_scatter.xlsx in 0.0138 seconds
19:12:47 Value of linest six foot from getCell(A32) : =LINEST(D1:D18 , C1:C18 , TRUE, TRUE)
19:12:47 Value of linest six foot used getCalculatedValue get cell A32 : 4.5410646714826
19:12:47 Value of linest ten foot from getCell(A42) : =LINEST(G1:G18 , F1:F18 , TRUE, TRUE)
19:12:47 Value of linest ten foot used getCalculatedValue get cell A42 : 1.8991284485724
I tried
$spreadsheet->getActiveSheet()->fromArray($linestSix ,null,'C32');
That does the same as setCellValue, described above.
Follow this link, enter link description here ,to see the browser output when I run my code to generate my chart, 33 Chart create scatter. Go down about 75 lines into the object to [Worksheet!A32] , There is my data, but, how do I get it out of there? I got that from the print_r of $linest6 below.
$linest6 = $spreadsheet->getActiveSheet()->setCellValue('A32', '=LINEST(D1:D18 , C1:C18 , TRUE, TRUE)');
echo 'The six foot data array : <br>';
echo '<pre>';
print_r($linest6);
echo '</pre>';
Would someone, maybe Mark Baker, help me get the statistics from linest, the same as I described above from the formula wizzard? Thank you.

I finally got it!! Many trips to Google. Reviewing how to retrieve an array from a class-function. Here is my final script.
$stats = new Statistical();
$statArr6 = $stats->LINEST($dataArraySixY, $dataArraySixX, TRUE, TRUE);
$statArr10 = $stats->LINEST($dataArrayTenY, $dataArrayTenX, TRUE, TRUE);
$worksheet->fromArray(
$statArr6,
NULL,
"C22");
$worksheet->fromArray(
$statArr10,
NULL,
'C32'
);
I have a little more to display the info as I want to, but I have the arrays.

Related

Date and Time Split, then added into another table column

EDIT:
I want to thanks #jimmix for giving me some idea to get started on my last post, But unfortunately, my post was put on hold. Due to the lack of details.
But here are the real scenario, I'm sorry if I didn't explain well my question.
From my CSV file, I have a raw data, then I will upload using my upload() function in into my phpmyadmin database with the table name "tbldumpbio",
See the table structure below:(tbldumpbio)
From my table tbldumpbio data, I have a function called processTimesheet()
Here's the code:
public function processTimesheet(){
$this->load->model('dbquery');
$query = $this->db->query("SELECT * FROM tbldumpbio");
foreach ($query->result() as $row){
$dateTimeExplArr = explode(' ', $row->datetimex);
$dateStr = $dateTimeExplArr[0];
$timeStr = $dateTimeExplArr[1];
if($row->status='C/Out' and !isset($timeStr) || empty($timeStr) ){
$timeStrOut ='';
} else {
$timeStrOut = $dateTimeExplArr[1];
}
if($row->status='C/In' and !isset($timeStr) || empty($timeStr) ){
$timeStrIn ='';
} else {
$timeStrIn = $dateTimeExplArr[1];
}
$data = array(
'ID' => '',
'companyAccessID' => '',
'name' => $row->name,
'empCompID' => $row->empid,
'date' => $dateStr,
'timeIn' => $timeStrIn,
'timeOut' => $timeStrOut,
'status' => '',
'inputType' => ''
);
$this->dbquery->modInsertval('tblempbioupload',$data);
}
}
This function will add another data into another table called "tblempbioupload". But here are the results that I'm getting with:
Please see the below data:(tblempbioupload)
The problem is:
the date should not be duplicated
Time In data should be added if the status is 'C/In'
Time Out data should be added if the status is 'C/Out'
The expected result should be something like this:
The first problem I see is that you have a time expressed as 15:xx:yy PM, which is an ambiguous format, as one can write 15:xx:yy AM and that would not be a valid time.
That said, if what you want is that every time the date changes a row should be written, you should do just that: store the previous date in a variable, then when you move to the next record in the source table, you compare the date with the previous one and if they differ, then you insert the row, otherwise you simply progress reading the next bit of data.
Remember that this approach works only if you're certain that the input rows are in exact order, which means ordered by EmpCompId first and then by date and then by time; if they aren't this procedure doesn't work properly.
I would probably try another approach: if (but this is not clear from your question) only one row per empcompid and date should be present, i would do a grouping query on the source table, finding the minimum entrance time, another one to find the maximum exit date, and use both of them as a source for the insert query.

Google Chart with Decimal Number

I have a ajax function which gives the response like:
[{"lot_no":"Lot A","sent_weight":"20.8","received_weight"
:"19.3"},{"lot_no":"Lot B","sent_weight":"6.8","received_weight"
:"5.3"},{"lot_no":"Lot C","sent_weight":"7.8","received_weight"
:"10.3"}]
I want to draw the google function chart on basis of Lot no, sent weight and received weight but the problem is :
Type mismatch. Value "20.8" does not match type number in column index 1
How can i make a google function chart with these sort of response data
Since PHP 5.3.3, there's a flag for auto-converting numbers (the options parameter was added in PHP 5.3.0):
$arr = array( 'row_id' => '1', 'name' => 'George' );
echo json_encode( $arr, JSON_NUMERIC_CHECK );
// {"row_id":1,"name":"George"}
This will help you.
Your ajax response is returning the string values in respective keys. Convert the string into float value example: parseFloat("10.33"), this will return number format.

Populating Google combo chart with multidimensional PHP array

I have a php array with data on students. It looks like this:
array(5) {
["question1"]=>
array(30) {
["2014, 03, 02"]=>
array(10) {
["student1"]=>
int(54)
["student2"]=>
int(43)
... etc. ...
["median"]=>
string(2) "49"
}
Each day the students answers five questions with a value from 1 to 100. Each day a median value for all answers to a single question is calculated. The answers and the median value is stored like above.
Now I want to populate a Google Charts combo chart with this data but I just can't get it to work.
I would like to visualise the data with the date on the X-axis, the 1-100 value on the Y-axis and each answer as a point. The data for the median value should be displayed as a curve over the points. Points and curves for each question should have its own colour.
But I'm pretty much stuck. I can't figure out how to insert the data. I have tried this approach:
var jsonData = (<?= json_encode($data)?>);
var data = new google.visualization.arrayToDataTable(jsonData);
but I only get the following error message:
Uncaught Error: Not an array format+da,default+da,ui+da,corechart+da.I.js:181
lda format+da,default+da,ui+da,corechart+da.I.js:181
Gp format+da,default+da,ui+da,corechart+da.I.js:183
drawChart ?side=graf:4888
You need to change the format of your data. The Visualization API expects data in a tabular format, where your x-axis data is in the first column and each data series (a set of colored points) is its own column of data. You can either construct a json representation of a DataTable (for use with the DataTable constructor) or an array of arrays of data (for use with the arrayToDataTable function).
Since you are already using the arrayToDataTable function, this is the structure you need to have:
$data = array(
array('Date', 'Question 1', array('type' => 'number', 'role' => 'interval', 'id' => 'Q1Median'), 'Question 2', array('type' => 'number', 'role' => 'interval', 'id' => 'Q2Median') /* repeat for other questions */),
// format is array(date, q1 score, q1 median, q2 score, q2 median...)
// set the median in the first row for the day, leave it null for all other rows
array('2014, 03, 02', 54, 49, /* repeat for other questions */),
array('2014, 03, 02', 43, null, /* repeat for other questions */),
// repeat one row for each student for each day
);
The median values are set in an "interval" role column, which you can style to display as a curved line in the chart options:
interval: {
// use the column ID of an interval to set the options for that interval
Q1median: {
style: 'line'
},
Q2median: {
style: 'line'
}
// etc...
}
Options for styling intervals are documented here.

add value to JSON of title

I search a lot in stack and google try to find the answer which seems to be easy but I'm still stuck with it
I write a code to encode json with values I wanted from . and I would like to add a key / value to the JSON
the JSON is as following structure
{
- files: [
{
title: "works",
- tracks: [
{
title: "File",
format: "mp3"
}
]
},
-{
title: "season1",
tracks: [
{
title: "Button-1",
format: "wav"
},
-{
title: "Beep-9",
format: "wav"
}
]
}
]
}
I want to add to that a key and its value at the beginning to the json as properties under the title files , I mean that can be read by code as
json[files][new_key]
I tried to set that value like this
$json['new_key'] = "new_value";
but this causes adding numbers to the arrays in json , I don't why they numbered
this numbers affect my reading way of the json as JSONModel in my iOS app
so , I hope you can help me
thanks in advance
Assuming that the new value you want to add varies by file, you would need to loop through $json[files] and insert them per key/value pair.
<?php
for($i=0; $i<count($json); $i++)
$json[files][$i]["new_key"] = "value";
?>
I'm still not sure what you have exactly, but it seems you are trying to manipulate the json string.
If done correctly, that is probably the most efficient solution, but what you could also do is:
use json_decode to generate an array from your json string;
locate the correct section / sub-array where you want to add your data;
use array_unshift to prepend your new key - value pair;
use json_encode to generate a json string from your complete array.
The reason you're getting numbers appearing is because you're adding a key to an array (which functions more or less as a list in JS). So before you basically have the object "files" as a list of objects zero-indexed like any other JS array. When you add the key, JS simply adds your key to the end of your present keys (in your case 0 and 1).
It seems like you have a list of multimedia objects where each has a title and a list of tracks. The most straightforward way to solve your issue would be as follows:
$fileItem['title'] = 'works';
$fileItem['tracks'] = array(
array(
'title' => 'File',
'format' => 'mp3'
)
);
$json['files'][] = $fileItem;
$fileItem['title'] = 'season1';
$fileItem['tracks'] = array(
array(
'title' => 'Button-1',
'format' => 'wav'
),
array(
'title' => 'Beep-9',
'format' => 'wav'
)
);
$json['files'][] = $fileItem;
Then you JSON encode it and return it as you normally would. You can put the above in a loop as well. I lack enough context to recommend exactly how.

Stripe API: List all Charges

I am using https://stripe.com/docs/api?lang=php#list_charges to get List all Charges but here they specify
count optional — default is 10 A limit on the number of objects to be
returned. Count can range between 1 and 100 items.
and I have thousands of entries, now how can I get all. Though if I set count to 100 it returns 110 records.
You can use the offset argument.
Once you get the 100 transactions, then make another call by adding offset=100 in URL.
This will bring the next 100 transactions, then make offset=200 and so on.
Update:
offset parameter is partly deprecated: API changelog - 2015-09-23
$charges = \Stripe\Charge::all();
foreach ($charges->autoPagingIterator() as $charge) {
// Do something with $charge
}
Reference.
Yes I got it with offset we can get all records.
Here's a PHP example: \Stripe\Charge::all(array("limit" => 3, "offset" => 10));
A Ruby example:
Stripe::Charge.all(limit: 3, offset:3)
As good as the Stripe API docs are, they could be clearer on how to filter.
source: https://stripe.com/docs/api/php#list_charges, https://stripe.com/docs/api/ruby#list_charges
in case offset is deprecated
$result = [];
$created_at = strtotime($request->end_data);
//created_at should be today's date epoch. search google for epoch
$has_more = false;
$a = 0;
do{
print_r($a);
\Stripe\Stripe::setApiKey(env('STRIPE_SECRET'));
$temp = \Stripe\BalanceTransaction::all( array(
'limit' => 100,
'created' => array(
'lte' => $created_at,
)
));
$result = array_merge($temp->data,$result);
$created_at = $temp->data[99]->created_at;
//api returns a parameter has_more(boolean), which means there is more
//data or not so you can also put that in while condition, for ex.
// $has_more = $temp->has_more;
$a++;
}while($a < 5);
dd($result);
this worked for me i was able to get 500 records at once as $a < 5 the api hits 5 times and each time created parameter which is lte (less than equal) changes for each api request and return previous records than current request provide. also i am appending the result of each api call to another result array
Unfortunately you can't.
I can see where such a feature would be nice for accounting purposes or whatever, but it's generally a better user experience to implement some sort of paging when displaying copious amounts of data to the user.
If you need absolute control over how many records to display at a time, I would suggest setting up a webhook on the charge.succeeded event and store your charges locally.

Categories