subblock create xlsx with opentbs? - tinybutstrong

Hello I hope you can help me. I am trying to use sub-blocks with the following array that you come from 2 mysql queries.
$data[$i]= array(
"ref"=>$row['ref'],
"label"=>$row['label'],
"unidad"=>$row['cu_label'],
"rawdata" => array(
"fecha"=>$ro['fecha'],
"stock_total"=>$ro['stock_total'],
"venta_unit"=>$ro['venta_unit'],
"venta_total"=>$ro['venta_total']
)
);
$TBS->MergeBlock('p', $data);
In the xlsx template I am calling like this
[p;block=begin;sub1=rawdata]
[p.ref]
[p.label]
[p.unidad]
[p_sub1.fecha;block=tbs:row]
[p_sub1.stock_total;block=tbs:row]
[p_sub1.venta_unit;block=tbs:row]
[p_sub1.venta_total;block=tbs:row]
[p;block=end]
but for the sud-block rawdata it gives me error item 'date' is not an existing key in the array.
any idea how i can solve. thanks

I can see several mistakes :
1)
The data for the sub-block should be a "recordset", that is an array of array.
In your snippet, you should replace:
"rawdata" => array(
"fecha"=>$ro['fecha'],
"stock_total"=>$ro['stock_total'],
"venta_unit"=>$ro['venta_unit'],
"venta_total"=>$ro['venta_total']
)
with:
"rawdata" => array(
array(
"fecha"=>$ro['fecha'],
"stock_total"=>$ro['stock_total'],
"venta_unit"=>$ro['venta_unit'],
"venta_total"=>$ro['venta_total'],
),
),
Thus the data structure is correct, but the sub block always have only one record. This is maybe not what you expect.
2)
The sub-block definition in the XLSX will not display 4 rows.
With OpenTBS, when you repeat "block=…" that produces alternative sections.
In order to have a sub-block defined on 4 rows you should write :
[p;block=begin;sub1=rawdata]
[p.ref]
[p.label]
[p.unidad]
[p_sub1.fecha;block=4*tbs:row] (this will define a block over 4 rows, including this one)
[p_sub1.stock_total]
[p_sub1.venta_unit]
[p_sub1.venta_total] (the last row of block 'p_sub1')
[p;block=end]
With XML templates such as Ms Officve or LibreOffice, it is not advised to define a block with the explict syntax (block=begin … block=end). This is because you cannot imaging where the XLM entities bounds are actually positioned.
And you need luck in order to have a valid XML result.
If you put a different color on each of you row in the template, then watch the color in the result. You’ll see that block=begin has broken some rows in the middle.
The good practice with OpenTBS is to define block bounds with the relative syntax, such as block=tbs:row.
I suggest you template should be :
[p;block=8*tbs:row;sub1=rawdata] (8 rows including the sub-block)
[p.ref]
[p.label]
[p.unidad]
[p_sub1.fecha;block=4*tbs:row] (this will define a block over 4 rows, including this one)
[p_sub1.stock_total]
[p_sub1.venta_unit]
[p_sub1.venta_total] (the last row of block 'p_sub1')

Related

JQuery aproach to count elements before and after: always same value

I have a table with columns and below, an icon upon clicking, I can modify the table columns.
Now I want to count the columns before and after. I have a solution which works, where I call the the following before and after and then use the wrapped alias (via parseInt) to compare:
cy.get('body').then(($el) => {
// eslint-disable-next-line #typescript-eslint/no-unsafe-assignment
const countColsNr = $el.find('th[e2e-tag-header]').length;
cy.wrap(**to be named**).as(`${s}`);
});
This counts the actual columns and saves it in the variable to be named.
However, if I use a JQuery approach, it always gets the same column number, which is at the beginning of the test:
const beforetColsNr = Cypress.$('th[e2e-tag-header]').length;
log(beforetColsNr.toString());
... column handling code
... also tried with wait inbetween steps for debug
const afterColsNr = Cypress.$('th[e2e-tag-header]').length;
log(afterColsNr.toString());
Before number and after, are the same! When I look at the state of the browser (screenshot), I can see different columns amount at time of counting in after. This JQ-approach does not count properly the second time or uses the first value.
Is this something which is expected? Or is something I have to investigate?
cypress is asyncrhonous, so beforetColsNr and aftterColsNr are initialized at the same moment.
In the "cypress" mode in your first code block it works because of the usage of the .then().

Cypress - counting number of elements in an array that contain a specific string

Attempting to confirm that of all the schema in the head of a page exactly 3 of them should have a specific string within them. These schemas have no tags or sub classes to differentiate themselves from each other, only the text within them. I can confirm that the text exists within any of the schema:
cy.get('head > script[type="application/ld+json"]').should('contain', '"#type":"Product"')
But what I need is to confirm that that string exists 3 times, something like this:
cy.get('head > script[type="application/ld+json"]').contains('"#type":"Product"').should('have.length', 3)
And I can't seem to find a way to get this to work since .filter, .find, .contains, etc don't filter down the way I need them to. Any suggestions? At this point it seems like I either need to import a custom library or get someone to add ids to these specific schema. Thanks!
The first thing to note is that .contains() always yields a single result, even when many element match.
It's not very explicit in the docs, but this is what it says
Yields
.contains() yields the new DOM element it found.
If you run
cy.get('head > script[type="application/ld+json"]')
.contains('"#type":"Product"')
.then(console.log) // logs an object with length: 1
and open up the object logged in devtools you'll see length: 1, but if you remove the .contains('"#type":"Product"') the log will show a higher length.
You can avoid this by using the jQuery :contains() selector
cy.get('script[type="application/ld+json"]:contains("#type\": \"Product")')
.then(console.log) // logs an object with length: 3
.should('have.length', 3);
Note the inner parts of the search string have escape chars (\) for quote marks that are part of the search string.
If you want to avoid escape chars, use a bit of javascript inside a .then() to filter
cy.get('script[type="application/ld+json"]')
.then($els => $els.filter((index, el) => el.innerText.includes('"#type": "Product"')) )
.then(console.log) // logs an object with length: 3
.should('have.length', 3);

Laravel 5.1 translate an array pass to blade

I have this in my controller
public function editProfile(Request $request){
$question1 = Question::where('group',1)->lists('question', 'id');
$question2 = Question::where('group',2)->lists('question', 'id');
return view('user', compact(''question1', 'question2'));
}
$question = {\"1\":\"What is the first name of your best friend in high school?\",\"2\":\"What was the name of your first pet?\",\"3\":\"What was the first thing you learned to cook?\",\"4\":\"What was the first film you saw in the theater?\"}
$question2 = {\"5\":\"Where did you go the first time you flew on a plane?\",\"6\":\"What is the last name of your favorite elementary school teacher?\",\"7\":\"In What city or town does your nearest sibling live?\"}
I would like to translate the value in both question 1 and question 2 and pass it to user blade without changing the key, Any suggestions?
As specified at the localization doc, you need to populate a lang file with translation strings. So, let's say you want to show both Spanish and English strings. In this case you'd need to create two files: /resources/lang/en/messages.php and /resources/lang/es/messages.php. The content of one of those files would be somewhat like this:
<?php
// resources/lang/es/messages.php
return [
'welcome' => 'Bienvenido'
];
This way, you could access the strings in there with the following method: __('messages.welcome'), which would return the string for the language set on your config/app.php -- the default entry is en, by the way, but you can set it to whatever you want. The value in there will define which language will be chosen when selecting strings.
Another method to create translation strings is using the string itself as key, storing them in a JSON file instead of PHP. For example, the following translation string:
{
"I love programming.": "Me encanta programar."
}
would be accessible through this: __('I love programming.').
Having said that, you may solve your problem through the two methods presented above. You could store in your DB keywords for the questions instead of the whole text, and create translation for as many languages as you want. Also, you could keep the questions in your database and create translation strings for those questions. Finally, you'd need to iterate over the fetched entries and translate each one of them, or use some Collection helper to do the hard work for you, like transform or map.

Need linq query

I have 3 fields(Name, Code, displayNmae) in the list, here I need to get a list as output in which I get all the fields but need to split displayname field by colon and then add list again for each splitted value which is display name.
Hence in output list I will have the 5 row as total display name are 5 in 2 rows.
Need the linq query for this problem.
Name Code displayName
Napkins_tableware - Napkins and tableware - 3_ply:conventional_napkins
hand-towel - Hand and Towel - 2_ply:towel roll:coloured
Output should be like this :
Name Code displayName
Napkins_tableware - Napkins and tableware - 3_ply
Napkins_tableware - Napkins and tableware - conventional_napkin
hand-towel - Hand and Towel - 2_ply
hand-towel - Hand and Towel - towel roll
hand-towel - Hand and Towel - coloured
Solution which I tried in C#
foreach(ProductDetailsWithFilters qs in CategoryProductList())
{
foreach(string friendlyname in qs.displayName.Split(':'))
{
qs.displayName = friendlyname;
tempCategoryProductList.Add(qs);
}
}
If you're translating to LINQ, when you have nested foreach loops those correspond to 'from' clauses in query syntax (or in dot syntax, subsequent ones become SelectMany, see below.) The following should be close to what you want:
var query =
from qs in CategoryProductList()
from friendlyName in qs.displayName.Split(':')
select new ProductDetailsWithFilters(qs.Code, qs.Category, friendlyName);
Note: Because functional programming should be side-effect-free, it's better to select a new instance ProductDetailsWithFilters than it is to modify the existing one in your query. My presumption is that you can call a constructor to build a new one of these.
For you to modify the existing property like your loop implementation does, you would have to iterate over the result -- LINQ doesn't provide such a thing in the framework. Such side-effects often lead to hard-to-find bugs.
To do the equivalent of the above query with a SelectMany and dot-syntax:
var query = CategoryProductList()
.SelectMany(
qs => qs.DisplayName.Split(':'),
(qs, friendlyName) => new ProductDetailsWithFilters(qs.Code, qs.Category, friendlyName));
Both lead to functionally identical code. In this case, I tend to prefer the query-syntax over the dot-syntax partly because because there are several SelectMany overloads and handling the projection involves repeating the variables across both lambda expressions. If you had another "from" to add, the query-syntax hides the management of 'transparent identifiers' that you would otherwise have to deal with in dot-syntax equivalent code. Whatever your preference, you now have both.
It's worth noting that queries are lazy -- they do nothing until you iterate over their result. So it's really what you do with the result from here that is the interesting part - store it .ToList(), directly data-bind it to a UI, use it to service a web-API, etc...

Is it possible to display an Image in an autocompletion-popup list (Gtk3)

I am using an Entry with an EntryCompletion opbject that has a ListStore model.
For each record in the model, there is an image I would like to display in the autocomplete-popup list.
How can this be done?
Is it possible to add a Gtk.CellRendererPixbuf column to the model?
Interesting enough I could not find any examples of this yet it turns out to be possible and not insanely complicated. Lets start with a small image of the goal which uses icons for convinces reasons.
So how do we get there, first we create the ListStore containing a column with strings to match on and a icon-name to convert into a pixbuf (this could also be a pixbuf directly).
# Define the entries for the auto complete
entries = [
('revert', 'document-revert'),
('delete', 'edit-delete'),
('dev help', 'devhelp'),
]
# Setup the list store (Note that the data types should match those of the entries)
list_store = Gtk.ListStore(str, str)
# Fill the list store
for entry_pair in entries:
list_store.append(entry_pair)
Next step is setting up the EntryCompletion and linking it with the Liststore
# Create the Entry Completion and link it to the list store
completion = Gtk.EntryCompletion()
completion.set_model(list_store)
Now the magic, we need to create 2 renderers, one for the text, one for the pixbufs. We then pack these in the completion to add columns to it.
# Create renderer's for the pixbufs and text
image_renderer = Gtk.CellRendererPixbuf.new()
cell_renderer = Gtk.CellRendererText.new()
# Pack the columns in to the completion, in this case first the image then the string
completion.pack_start(image_renderer, True)
completion.pack_start(cell_renderer, True)
In order to make sure the renderers use the the correct column we here specify which column from the ListStore the renderers should read. For the image_renderer we set the icon_name attribute as we give it icon names. If we would feed it Pixbuf's we would need the pixbuf instead.
# Set up the renderer's such that the read the correct column
completion.add_attribute(image_renderer, "icon_name", 1)
completion.add_attribute(cell_renderer, "text", 0)
As there are no multiple column we need to tell the completion which column contains the string. In our case column 0.
# Tell the completion which column contains the strings to base the completion on
completion.props.text_column = 0
# Create the entry and link it to the completion
entry = Gtk.Entry()
entry.set_completion(completion)
And that's it!

Resources