I need to apply conditional formatting on a dynamic range by axlsx. That is, in the example below, replace the 'A2:A10' by something like
'A2:A' & sheet.rows.last
as it would work in excel VBA
red = styles.add_style(:bg_color=> 'FFFF0000', :type => :dxf)
# Apply conditional formatting to range A2:A10 in the worksheet
sheet.add_conditional_formatting('A2:A10', { :type => :cellIs,
:operator => :equal,
:formula => "1",
:dxfId => red,
:priority => 1 })
I studied the documentation and tried some versions without success.
I'm not very familiar to axlsx, but want to extend functionality of an existing project. Thank you very much in advance!
Related
I could not able to find in the documentation on how to get only updated records/rows from Google Sheets API.
Is there a way, that I can get a timestamp of each record when it was last modified?
any guidance or any links that would solve this issue.
Thanks!
You cannot do this directly with Sheets API. You can keep track of the changes in a file using Drive API, though, but I don't think this is what you want to do.
I'd propose using an onEdit trigger using Apps Script. Every time the spreadsheet is modified, you could retrieve the data of the edited range and store it somewhere, as well as the current date.
It could be something on the following lines:
function onEdit(e) {
var timestamp = new Date();
var range = e.range;
var editedRow = range.getRow();
// Store timestamp and editedRow index somewhere you can retrieve it later (it could be in the spreadsheet itself)
}
Update:
You can create the trigger remotely using Apps Script API. First you should create a project bound to your spreadsheet and then add the corresponding code by calling projects.updateContent (you should add two files, the script itself, which contains the onEdit trigger, and the manifest file). Just beware that you can only use simple triggers with this API, not installable ones. But in your situation, that's more than enough.
I hope this is of any help.
WRITE OPERATION:
For $response = $service->spreadsheets_values->update() process (Writting file after creating it), response will be as follow:
Google_Service_Sheets_UpdateValuesResponse Object
(
[spreadsheetId] => XXX
[updatedCells] => 7
[updatedColumns] => 7
[updatedDataType:protected] => Google_Service_Sheets_ValueRange
[updatedDataDataType:protected] =>
[updatedRange] => Sheet1!A1:G1
[updatedRows] => 1
[internal_gapi_mappings:protected] => Array
(
)
[modelData:protected] => Array
(
)
[processed:protected] => Array
(
)
)
To Get Rows = $response->getUpdatedRows();
To Get Cells = $response->getUpdatedCells();
To Get Columns= $response->getUpdatedColumns();
and so on...
APPEND OPERATION:
For $response = $service->spreadsheets_values->append() process, response will be as follow:
Google_Service_Sheets_AppendValuesResponse Object
(
[spreadsheetId] => XXXX
[tableRange] => Sheet1!A1:G1
[updatesType:protected] => Google_Service_Sheets_UpdateValuesResponse
[updatesDataType:protected] =>
[internal_gapi_mappings:protected] => Array
(
)
[modelData:protected] => Array
(
[updates] => Array
(
[spreadsheetId] => XXXX
[updatedRange] => Sheet1!A2:G7
[updatedRows] => 6
[updatedColumns] => 7
[updatedCells] => 42
)
)
[processed:protected] => Array
(
)
)
To Get Rows = $response->getUpdates()->getUpdatedRows();
To Get Cells = $response->getUpdates()->getUpdatedCells();
To Get Columns= $response->getUpdates()->getUpdatedColumns();
and so on...
I have a form which has date_of_purchasing and expiry_date. I need to check date_of_purchasing should not be greater than expiry_date. How can i write this validation rule in model.
Im using YII framework. And im new for this framework.
Yii2
This should work if the compared column comes from the same table.
public function rules()
{
return [
[
['date_end'],
'compare',
'compareAttribute' => 'date_start',
'operator' => '>=',
'type' => yii\validators\DateValidator::TYPE_DATE,
'message' => 'Date end has to be greater than date start',
'enableClientValidation' => false
],
// other rules...
];
}
Don't forget to set enableClientValidation to false because Yii2 can't check the other date without a server side request.
Other configuration options here.
PS. I decided to update this thread 3+ years after because it remains
one of the first StackOverflow results on Google Search for this argoument.
Try to use CompareValidator at this link: Compare .
I want to style the background color of an axlsx created sheet based upon cell content that is a word (ie. 'Pass' or 'Fail')
I can format the sheet if the cell content is a number. I've tried changed type => :containsText and adding :text => "Fail" but with no success. I can change the cell content to 'Fail' easily, but then I cannot get the conditional styling to work.
This is the code that works great if the cell values are numbers (in this case 2):
red = styles.add_style(:bg_color=> 'FFFF0000', :type => :dxf)
# Apply conditional formatting to range I:L in the worksheet
sheet.add_conditional_formatting('I:L', { :type => :cellIs,
:operator => :equal,
:formula => "2",
:dxfId => red,
:priority => 1 })
But if I change the :formula => "Fail" then it doesn't work. I've tried changing :type => containsText and a bunch of combinations.
Took some more fiddling around, but here's the answer :)
red = styles.add_style(:bg_color=> 'FFFF0000', :type => :dxf)
sheet.add_conditional_formatting('I:L', { :type => :containsText,
:text => "Fail",
:operator => :equal,
:dxfId => red,
:priority => 1 })
I'm making a rails application so that users can search a database of midi records and find midi files that correspond to the attributes that I've given them.
For example, a user might enter data into an html form for a midi file with name = "blah" composer= "buh" and difficulty = "insane".
This is all fine and well, except that I would like when the user enters no data for a field, that field is ignored when doing the select statement on the database.
Right now this is what my select statement looks like:
#midis=Midi.where(:name => params[:midi][:name],
:style => params[:midi][:style],
:numparts => params[:midi][:numparts],
:composer=> params[:midi][:composer],
:difficulty => params[:midi[:difficulty])
This works as expected, but if for example he/she leaves :composer blank, the composer field should not considered at all. This is probably a simple syntax thing but i wasn't able to find any pages on it.
Thanks very much!
Not sure if Arel supports that directly, but you could always do something like:
conditions = {
:name => params[:midi][:name],
:style => params[:midi][:style],
:numparts => params[:midi][:numparts],
:composer=> params[:midi][:composer],
:difficulty => params[:midi[:difficulty]
}
#midis=Midi.where(conditions.select{|k,v| v.present?})
Try this:
# Select the key/value pairs which are actually set and then convert the array back to Hash
c = Hash[{
:name => params[:midi][:name],
:style => params[:midi][:style],
:numparts => params[:midi][:numparts],
:composer => params[:midi][:composer],
:difficulty => params[:midi][:difficulty]
}.select{|k, v| v.present?}]
Midi.where(c)
Another noob question that seems like it should be simple:
Thanks to the help received here, I can easily get a sum of selected transactions:
#trip_hash = transactions.sum(:amount_cents, :group => :trip_id)
The issue, however, is that the :amount_cents column represents a raw Money object that needs to be transformed before summing in order to accommodate currency exchange. The Money "composed of" Procs look like this:
composed_of :amount,
:class_name => "Money",
:mapping => [%w(amount_cents cents), %w(currency currency_as_string)],
:constructor => Proc.new { |cents, currency| Money.new(cents || 0, currency || Money.default_currency) },
:converter => Proc.new { |value| value.respond_to?(:to_money) ? value.to_money : raise(ArgumentError, "Can't convert #{value.class} to Money") }
I can easily call:
transactions.map(&:amount).inject(:+)
to get a transformed grand total, but I can't figure out how to do it in the context of the groupings.
Many thanks, again, for the help!
Took a lot of canoodling and reading, but finally figured out the following:
trip_hash = bankroll.transactions.group_by(&:trip_id).map {|tr,t| Hash[tr, t.map(&:amount).inject(:+)]}
=>[{0=>#<Money cents:137693 currency:USD>}, {7=>#<Money cents:-39509 currency:USD>}, {10=>#<Money cents:50009 currency:USD>}]
Map within the map did it! Hashifying makes it view friendly, and it retains the Money object for formatting purposes....