Hi I have a pChart 2 bar chart which contains a variable number of bars and as well as the actual value for each bar I wish to display 2 additional values to the right hand side of each bar. Please consider the image below where the values in the rectangle are an example of the figures I need to add to the chart.
Obviously I want to make them look a bit neater than this but really at the moment I am just wondering
What would be the correct way to do this in pChart?
Is there a built in way to perform this kind of decoration?
If not, how should I best align my additional output with each bar in the chart, considering that these bars are variable in pixel size and data size (i.e. this has to be calculated not approximated for a single scenario).
Just for clarity the extra figures are simply the same scores from previous years and would be decorated in a colour border or similar and included in a legend.
Thanks.
In the drawBarChart() method of the file pDraw.class.php there is the following conditional at the end of that method:
if ($DisplayPos == LABEL_POS_INSIDE && abs($TxtWidth) < abs($BarWidth)){
...
else{
At the end of that else block is a $this->drawText() method, this outputs the value on the end of the bar and will be called for each bar in the series. You can also at this point write additional values to the end of the chart (in this case the right margin) using the following:
$itemGap = 45; //the space between items
$items = array(1,2,3); //the value to draw
$colStart = $this->GraphAreaX2 + $itemGap;
foreach($itemGap as $item)
{
$this->drawText($colStart, $Y + $YOffset + $YSize / 2, $item, array("R" => $DisplayR, "G" => $DisplayG, "B" => $DisplayB, "Align" => $Align, "FontSize" => $DisplaySize));
$colStart += $itemGap;
}
I hope that is helpful to someone.
Related
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.
I have a list of ads, I would like to rotate them based on the rotation (which represents a percentage) and the number of times it has been viewed. There can be any number of ads, and they are listed within a multidimensional array. Each line is one ad. Each time it is viewed, viewed increases +1.
$aAd[] = array('viewed' => 2003, 'rotation' => 70); // 70%
$aAd[] = array('viewed' => 122, 'rotation' => 30); // 30%
I am trying to work out how to select the next ad to display based on the rotation and the number of times it has been viewed. Is anyone able to help with the formula to do this?
The algorithm needs to select the next one to display, it should choose it based on the number of times it has been viewed and the percentage it should be viewed (the rotation). The order of the ads are not presently in any specific order. The rotation represents the desired percentage in which the client would like the ads displayed. It is fine if an ad is picked twice in a row, as long as the rotation equals out to 70/30 in this example. Keep in mind, there can be any number of ads and they can have different rotations assigned as well.
You could use this function:
function getNextAdIndex($aAd) {
$scores = array_map(function ($ad) { return $ad["viewed"] / $ad["rotation"]; }, $aAd);
return array_search(min($scores), $scores);
}
It returns the index in $aAd that is the one that has the least views in comparison with what it ideally should have (based on its rotation percentage).
Example use
$aAd[] = array('viewed' => 0, 'rotation' => 70); // 70%
$aAd[] = array('viewed' => 0, 'rotation' => 30); // 30%
// Provide the next 100 views:
for ($i = 0; $i < 100; $i++) {
$j = getNextAdIndex($aAd);
echo "showing add $j\n"; // Do whatever is needed to "display" an ad here
$aAd[$j]["viewed"]++; // Increase its number of views
}
I have this code:
$plot = new PHPlot();
//Define some data
$example_data = array(
array('Learning',1),
array('Reading',3),
array('Writing',3),
array('Oral Communication',1),
array('Numeracy',2),
);
$plot->SetDataValues($example_data);
Now I get this graph:
My question is that How can I set the yAxis Text labels into static value like 1,2,3 and 4 only.. and not just like now 3.2,3,2.8,2.6 .. 2,1.8,1.6 ... 1, 0.8,... 0 .. ??
is it possible ?
One possibility would be to use the SetYTickIncrement() method.
$plot->SetYTickIncrement(1);
Don't forget, there's also the TuneYAutoTicks() method.
Bit stuck on how to achieve this.....
I have a PHP page which shows information for one record in a table. These records include a unique key (image_id) AND a name (image_name).
In order to display the correct record, I am using a search function on a previous page which results in a URL parameter (imageinfo.php?image_id=1 etc).
My problem is that I wish to add forward and back arrows to the table to cycle through different records, BUT based on the alphabetical order of 'image_name' rather than the numerical order of 'image_id.
I'm really not sure how to achieve this, so any help would be appreciated.
Something like this: (I hope the comments will explain)
<?php
$data = array(
123 => "B",
321 => "C",
124 => "A"
);
$id = 123; // This is the current image id
asort($data); // Sort the array based on values (names)
// Advance the internal pointer until it points to the current image
while(current($data) != $data[$id])
next($data);
// TODO: Also check whether next is past end here
echo next($data); // Should be C
I'm trying to change the sorting of my products.
I want to use the attribute sort by options not to sort by name but rather sort by position given in the "manage attributes". But only when there's a position (when all is 0 it should sort by name).
For this I need to know in which file the sorting is applied to the product collection. I searched inside app\code\core\Mage\Catalog\Model\Config.php and app\code\core\Mage\Catalog\Block\Product\List.php but neither found anything about the sorting. And maybe some code suggestions, too.
Google isn't helping me with this issue, too so I try it here. Maybe somone can help me with this.
Thanks
EDIT:
As example we take the "Color" attribute, it's a drop-down attribute.
The table inside "manage attributes" looks like this:
Valuename | Position
========================
light blue | 1
blue | 2
dark blue | 3
light red | 4
red | 5
dark red | 6
In the frontend I sort by the attribute "Color" and my products will be listed this way:
blue
dark blue
dark red
light blue
light red
red
But I want it to be listed like this:
light blue
blue
dark blue
light red
red
dark red
EDIT2:
public function getAllOptions($withEmpty = true, $defaultValues = false)
{
$storeId = $this->getAttribute()->getStoreId();
if (!is_array($this->_options)) {
$this->_options = array();
}
if (!is_array($this->_optionsDefault)) {
$this->_optionsDefault = array();
}
if (!isset($this->_options[$storeId])) {
$collection = Mage::getResourceModel('eav/entity_attribute_option_collection')
->setPositionOrder('asc')
->setAttributeFilter($this->getAttribute()->getId())
->setStoreFilter($this->getAttribute()->getStoreId())
->load();
$this->_options[$storeId] = $collection->toOptionArray();
$this->_optionsDefault[$storeId] = $collection->toOptionArray('default_value');
}
$options = ($defaultValues ? $this->_optionsDefault[$storeId] : $this->_options[$storeId]);
if ($withEmpty) {
array_unshift($options, array('label' => '', 'value' => ''));
}
return $options;
}
This is almost impossible to achieve if you want to go with the actual color attribute.
The product collection can get the text value of each color from the EAV structure and run a sorting based on it. But the attribute option table isn't joined to the collection, so there's no way it could know what position you've set for your options.
I would make an workaround for that, maybe not the best overall solution, but you'll get what you want.
Create an attribute with code smth like sorting_color and label Color, and numerical options (e.g. 1,2,3). And assign proper values to each product (so "light blue" would be 1, "blue" is 2 - and so on). Then remove the actual color attribute from sorting, and add your newly created sorting_color.
As I said not the exact solution, but you could get yourself into troubles if you choose to mess up with the product collection sorting.
I was also facing the same problem and solved it by using some custom code:
I want to share here so that someone will get idea from this:
First I got all attributes options of color sorted by their position
$attribute = Mage::getSingleton('eav/config')->getAttribute('catalog_product', 'color');
if ($attribute->usesSource())
{
$options = $attribute->getSource()->getAllOptions('positions');
}
foreach($options as $val)
{
$color_attr_array[] = $val['label'];
}
I obtained all the attribute options of color sorted by their position
foreach($childProducts as $_childProduct)
{
//get the attribute option of a particular product and find itd key from the attributes array
$color_attr_val = $_childProduct->getAttributeText('color');
$color_pos = array_search($color_attr_val,$color_attr_array);
//make a new array with key indexes of attribute options
$_childproduct_final_arr[$color_pos] = $_childProduct;
}
ksort($_childproduct_final_arr);
//This is the final array of products sorted by attribute options position
I found the function addValueSortToCollection in Mage_Eav_Model_Entity_Attribute_Source_Table is what defines the sort order. By adding a LEFT JOIN to the table eav_attribute_option and pulling in the sort_order field I was able to sort by the adminhtml position of the attribute. I haven't tested fully but it seems to do what I want.
I created a separate module to rewrite this class, the only modification is to addValueSortToCollection, below this line:
Mage::getResourceModel('eav/entity_attribute_option')
->addOptionValueToCollection($collection, $this->getAttribute(), $valueExpr);
I added the following Join, and modified the getSelect statement to sort by position 1st, then alphabetical second:
// add join here to pull in sort_order for attribute
$collection->getSelect()->joinLeft(
array($this->getAttribute()->getAttributeCode() . '_option' => 'eav_attribute_option'), "{$this->getAttribute()->getAttributeCode()}_option_value_t1.option_id=" . $this->getAttribute()->getAttributeCode() . "_option.option_id"
);
$collection->getSelect()
->order("sort_order {$dir}") // Add sort_order to the select statement
->order("{$this->getAttribute()->getAttributeCode()} {$dir}");
return $this;
}
Hope someone finds this helpful.
de
Just open this file Mage/Eav/Model/Entity/Attribute/Source/table.php and there is one function is there getAllOptions() in which try this
$collection = Mage::getResourceModel('eav/entity_attribute_option_collection')
->setPositionOrder('asc')
->setAttributeFilter($this->getAttribute()->getId())
->setStoreFilter($this->getAttribute()->getStoreId())
->load();
OR
please try to see weather there is comment or not this in app/code/core/Mage/Catalog/Model/Config.php:
public function getAttributeUsedForSortByArray()
{
$options = array(
**‘position’ => Mage::helper(‘catalog’)->__(‘Position’)**
);
foreach ($this->getAttributesUsedForSortBy() as $attribute) {
/* #var $attribute Mage_Eav_Model_Entity_Attribute_Abstract */
$options[$attribute->getAttributeCode()] = $attribute->getStoreLabel();
}
return $options;
}
may this will help you
let me know if you still facing any problem