That's a simple question.
I'm building a PHP Excel from scratch and is a very useful package.
I need to catch the active cell or row to know which cells to modify and customize, I checked all methods in the package and I didn't found something that helped me.
I'm inserting some data like this:
$sheet->appendRow(array(
$variable->value1,
$variable->value2,
$variable->value3,
));
And then I want to customize some things(This example I'm changing the background color), something like:
//The XXX is the last active row that I append some value before
$sheet->cells('XXXX',function ($cells){
$cells->setBackground('#34EC34');
});
There's some way to do find out the active cell or row to put in place of the 'XXX'? I found some question on Stack that someone was accessing by the variable $row, but I didn't found how to access....
go to class name "LaravelExcelWorksheet" in vendor/maatwebsite/excel/src/Maatwebsite/Excel/Classes/LaravelExcelWorksheet.php
Try to change method modifier of getStartRow from protected to public
You can use it with $sheet->getStartRow(), that's show you active row
Kaew's answer works, but to do this without modifying then LaravelExcel source, you can just use the method that getStartRow() uses internally - getHighestRow() - and add to the returned value if needed.
Here is the Laravel Excel 2.1 source for the getStartRow() method.
Related
I would like to use the Google Sheets API Batch Update because the calls to update individual cells are extremely slow. The problem is that cells that have no data do not come back as part of a cell feed, so I do not have the necessary edit URL to include those cells in the Batch Update. I have seen reference to a "return-empty" parameter in the Google .NET API which will supposedly return all cells, even empty cells, in a cell feed, but I cannot find any reference to that for the "Protocol" API I am using in PHP (here is an example of a reference to the "return-empty" parameter: Writing to an empty cell in Google Spreadsheets). Does anyone know how to get the cell feed request to return all cells (including empty cells)? Or am I doomed to using the abysmally slow cell update requests?
Quick Hack
If you're using the same API I am, then in googlespraedsheet/api.php at line 152 after
$cellRangeCriteriaQuerystringList = [];
You can add:
$cellRangeCriteriaQuerystringList[] = "return-empty=true";
Better Way
There's a better way, which I have added in my own fork. I created a pull request.
If you work with my fork (or if the pull request is accepted), then you can just add 'returnEmpty' => true to your $cellRange. For example:
$cellList = $spreadsheetAPI->getWorksheetCellList(
$spreadsheetKey,
$worksheetID,
['rowStart' => $rowStart,
'rowEnd' => $rowEnd,
'returnEmpty' => true]);
I have spent hours searching to find where magento stores full county name.
We can get a full list of countries using this code:
$_countries = Mage::getResourceModel('directory/country_collection')
->loadData()
->toOptionArray(false);
This will return an array with country code and name, I investigated the directory module, and found out this call gets data from the table
directory_county
But this table don't have full county name! So where is it stored?
and how is it retrieved using that call?
Thanks in advance.
Ok so to compensate for my wrong answer. Here is how this works:
/lib/Zend/Locale/Data/en.xml - if your store is in english, else another xml in the same directoery is read. Every country is there and its code under the xml tag <territory>
The xml is cached using the Zend_Cache_Core class.
/lib/Zend/Locale.php - function getTranslation invokes the lib/Zend/Cache/Core.php class
to load from the cache.
Example: If you change the name of some country in en.xml and clear the magento cache. You will see the change when u invoke your code again.
Full country names are not stored in database. Magento uses inbuilt Zend functionality.
Check file: lib/Zend/Locale/Data/Translation.php for full list.
Use the Zend_Local translation.
<?php
$code = 'EN';
echo Mage::app()->getLocale()->getTranslation($code, 'Territory', null, 2);
?>
Use the column 'iso2_code' from the table 'directory_country' for your $code.
Magneto only stores country codes in DB, and relies for names on Zend's Locale module to provide translated names, for different locale.
By the toOptionArray method it invokes the Zend_Locale class to get the translated value.
Refer $name = Mage::app()->getLocale()->getCountryTranslation($data['value']);, which gets to Mage_Core_Model_Locale and then to Zend_Locale.
It decides which of the node from the data to read, by the switch case statement in Zend_Locale_Data::getContent() line# 962, 963
Magento caches the names, so if you make any change to XML files, make sure to clean your cache folder to get what you seek.
I'm trying to perform a mass assignment of 2 variables I'm sending via GET to another model::controller (from project::actionCreate to client::actionCreate)
In the _form view for project::actionCreate I've got the following:
<?php echo " ".Chtml::link('+New client',array('client/create',array('Client' => array('redir'=>Yii::app()->controller->route,'redirId'=>$model->id))));?>
With the goal of creating an array "Client" with attributes "redir" and "redirId".
In client::actionCreate I want to do something like
if(isset($_GET['Client']))
{
$model->attributes=$_GET['Client'];
}
Now I noticed that my $_GET var puts client inside subarray 0, so I've tried this with
$_GET[0]['Client']
as well, but no luck. However if I manually assign the variables like this:
$model->redir = $_GET[0]['Client']['redir'];
$model->redirId = $_GET[0]['Client']['redirId'];
Then it works.
Any idea what is up? The goal is to allow someone to create a new client while creating/updating a project record, by sending them to client::actionCreate, but redirecting them back to their original project::actionCreate if they were linked there from my "+New Client" link.
I think the client array is put inside subarray 0 because you've added an array around the parameters. Try removing the array like the following:
<?php
Chtml::link('+New client',array('client/create', 'Client' => array('redir'=>Yii::app()->controller->route,'redirId'=>$model->id)));
?>
I don't know what your model looks like but if the fields aren't assigned they are probably not safe. You can make them safe by adding them to the rules part of your model. Or you could try the following, by specifying the false parameter it will be possible to assign values to unsafe attributes. (http://www.yiiframework.com/doc/api/1.1/CModel#setAttributes-detail)
$model->setAttributes($_GET['Client'], false);
I am not sure creating a link like you want is possible. I have asked something similar some time ago Yii link with [ as a parameter I just could never get the link to how I wanted it. In the end I just created the link the old fashion way, not using CHTML.
I have some questions concering routing with Codeigniter. What I´m doing now is the following:
$route['articles/(:num)'] = 'articles/view/$1'; // $1 will contain an ID
This means that example.com/articles/123 will work perfectly and load an article with an ID of 123. But I also want to have the possiblilty to add the aticle´s title to the URL (for SEO). Example: example.com/articles/123/article-title
What I want is pretty much the same thing as Stack Overflow: stackoverflow.com/questions/123/the-title
How can I do that?
I´m also wondering how Stack Overflow works. If I go to stackoverflow/questions/111 the title will automatically be added to the url. Is that done with php redirect()?
I have done something similar in the past; I can't find it know but IIRC (it was months ago) You can use a route like you did, and also add a more specific one, like
$route['articles/(:num)/(:any)'] = 'articles/view/$1/$2';
$route['articles/(:num)'] = 'articles/view/$1';
As you can see, both map to the same method, which is kind of "overloaded"; you can make up for a missing parameter by using a default value:
function articles($id,$slug = FALSE)
{ }
and simply ignore the second parameter in your article retrieval.
As for adding the title you can:
have a "slug" field in your database, created when the article is saved. You can use the comfortable url_title($title,'dash',TRUE) function (in the url helper), which takes the $title, uses the dash as separator, and make it all lowercase;
use the above function and convert the title of the article (after you retrieved it from the database) "on-the-fly"; just check on the article() method if the 2nd parameter isn't false and you'll know if you need to create the slug or not;
As for how to show the slug even when using an url without it you can make, as you guessed, a redirect, but since both routes point to the same method it won't change anything for you.
Oh, uhm, beware of loops while calling the redirect, check carefully ;)
I suggest you to create a slug field into your table and complete it with the url you want to use as id.
Let me explain.
You have this table
id
title
slug
when you save an article into your db you can dinamically create a slug, for example:
id: 1
title: My first post
slug: 1-my-first-post
then you can use the slug (in this case 1-my-first-post) ad id for the page, you can call it:
www.example.com/articles/1-my-first-post
obviusly you need to handle it in your db slect
As we discussed on the comments.
You can create a route several times and with different parameters each, like:
$route['articles/(:num)/(:any)']
$route['articles/(:num)']
I would create a function with a redirect, adding or not the title to it.
Hope it helps.
I'm trying to create a node (B type) & assign it to a A type node's CCK nodereference field using node_save() method.
$node_type_A = node_load($some_nid);
$node_type_A->field_type_B_node_ref[]['nid'] = $node_type_B_nid;
$node_type_A = node_submit($node_type_A);
node_save($node_type_A);
As the result, a new B type node will be created, but no reference will be assigned to the A type node. any help would be appreciated.
GApple is right, the format is correct, but there are couple of things that you might want to care about.
Delta Value
First you need to know the delta value of the latest node reference attached to $node_type_A, the delta is actually a partial index, when combined with vid field of the $node_type_A, they become the index for node reference table in the database. In other words, its a count for $node_type_B which are referenced in $node_type_A, ok?
GApple is right again, you have to exactly say where to add the new reference. When you got that delta value you can exactly say where to append (delta+1) the new reference. Here it is:
function get_current_delta($node_vid){
return db_result(db_query("SELECT delta FROM {content_field_type_A_node_ref}
WHERE vid = '%d'
ORDER BY delta DESC
LIMIT 1", $node_vid));
}
Adding the new reference
We got delta! so we can attach the new $node_type_B node to our $node_type_A node:
// Loading type_A node.
$node_type_A = node_load($some_nid);
// Getting current delta value.
$current_delta = get_current_delta($node_type_A->vid);
// "Appending" a node reference based on delta.
$node_type_A->field_type_B_node_ref += array($current_delta + 1 => array('nid' => $node_type_B_nid));
Resaving the updated node
Optionally call node_submit() to populate some essential fields in the node object and save it by utilizing node_save(). After all, you need to call content_insert() to make the node completely saved asidelong with its CCK fields:
// Resaving the updated node.
$node_type_A = node_submit($node_type_A);
node_save($node_type_A);
content_insert($node_type_A);
Flushing the content cache
Probably the most important part, this was killin' me for couple of days. CCK has a cache table in the database called cache_content (take a look at its structure), after resaving the updated node, you will notice that nothing has changed in the $node_type_A theme output even though that the tables are updated. We have to remove a record from that content cache table, this will force Drupal to show the latest snapshot of the data. You can define the following as a function:
db_query("DELETE FROM {cache_content} WHERE cid = '%s'", 'content:' . $node_type_A->nid . ':' . $node_type_A->vid);
Hope it helps ;)
I just checked one of my own modules that does something similar for the object format, and $node_type_A->field_type_B_node_ref[]['nid'] should be correct.
One thing to check for is that when you load the node, CCK may pre-populate the node reference array with an empty value. If you have configured the field to only allow one value, by using the array append operator (field_type_B_node_ref[]) it will create a second entry that will be ignored (field_type_B_node_ref[1]), instead of overwriting the existing value (field_type_B_node_ref[0]). Try explicitly specifying the array key if possible.
Great post, but one correction: don't flush cache entries by manually querying the DB. In the event someone is using memcache or any other external cache it's going to fail.
cache_clear_all() is your friend for clearing.
Suggested code, direct from the CCK module:
cache_clear_all('content:'. $node_type_A->nid .':'. $node_type_A->vid, content_cache_tablename());
I show CCK storing node references as $node->field_node_reference[0]['items'][0]['nid'], not $node->field_node_reference[0]['nid']. Have you tried mimicking that?
"Flushing the content cache" This works for me, especially if you get a data from node_load()