I am processing DOCX files for invoices with TBS. A first TBS block contains all the taxable items, one per line, followed by lines for subtotal and tax. A second TBS block contains all the non-taxable items, followed by one line for grand total.
I would like to leave out the first block, the subtotal and the tax amount if there are no taxable items.
I also would like to leave the second block out if there are no non-taxable items.
This is the basic structure:
[ItemListTx;block=begin]
[ItemListTx.s] [ItemListTx.a]
[ItemListTx;block=end]
subtotal [abk.tt]
tax [abk.tx]
[ItemListEx;block=begin;enlarge=tbs:p]
[ItemListTx.s] [ItemListTx.a]
[ItemListEx;block=end;enlarge=tbs:p]
total [abk.ttlx]
I wrapped the first five lines into a guarding block with a condition under which to display it:
[onshow;block=begin;enlarge=tbs:p;when 0=1]
...
[onshow;block=end;enlarge=tbs:p]
I did the same for the second block. This works OK. Note that the wrapper block statements are on different lines.
I am still a bit unhappy with the condition though. Is there any other way than setting a flag on the PHP side? It seems to me the second block should do without a wrapper, too.
Note: For editing reasons each item line is a table in itself, really.
Here is how it can easily be done:
| [ItemListTx.s;block=tbs:row;bmagnet=3*tbs:row] | [ItemListTx.a] |
| Subtotal: | [abk.tt] |
| Tax: | [abk.tx] |
| [ItemListEx.s;block=tbs:row;bmagnet=3*tbs:row] | [ItemListEx.a] |
| Total: | [abk.ttlx] |
Explanations:
Parameter bmagnet enabled you to define the block to delete when the data to merge with MergeBlock() are empty.
3*tbs:row means 3 successive table rows.
With OpenTBS it is not recommended to use explicit blocks (block=begin/block=end) because we cannot be sure where they is placed in the inner XML. It is better to use relatives blocks (such as block=tbs:p).
Related
Much ink has been spilled on the topic of sum types in SQL. The standard solutions are called absorption, separation, and partition; see, e.g.: https://www.inf.unibz.it/~montali/teaching/1415/dpm/slides/4.relational-mapping.pdf .
I want to ask about how to encode open sums. Normal sums allow a field to be one of a fixed set of several different types; with open sums, this set is not fixed.
The basic setup in our program: There is a list of "triggers," where each trigger can be one of many different things. Plugins can be written defining new trigger types, although the set of trigger types can be assumed to be known at compile time.
We want a table of all triggers.
Our current best idea:
Dynamically create a materialized view of the following form:
id | id_in_plugin_table | thing_in_main_program_it_refs | plugin_name
---------------------------------------------------------------------
1 | 27 | 8 | RegexTrigger
2 | 27 | 12 | RidiculouslyUnsafeCustomJSTrigger
This relation is automatically generated from the various plugin tables, each of which have their own ID and a thing_in_main_program_it_refs field.
For illustration, here's what the referenced tables may look like.
RegexTrigger table:
id | thing_in_main_program_it_refs | regex
---------------------------------------------------------------------
27 | 8 | hel*o
RidiculouslyUnsafeCustomJSTrigger
id | thing_in_main_program_it_refs | custom_js
---------------------------------------------------------------------
27 | 12 | (x) => isPrime(x.length())
Either use two roundtrips to lookup the plugin table and then query it, or combine them into a single SQL program which uses EXEC.
I'm happy with part 1, but not with part 2. Neither option sounds efficient, and the latter option uses EXEC.
So, we're looking for either (a) a better way to dynamically select a table in a query, or (b) a different approach to open sums.
I have a table called "tax_info", this table stores the information of the land tax of my city, it goes like this:
taxpayer_code | condominium_num | lot_area | built_area
-------------------------------------------------------------
0010030078-2 | 00-0 | 143 | 130
0010030079-1 | 02-7 | 283 | 57
0010030080-1 | 02-7 | 283 | 48
0010030081-1 | 02-7 | 283 | 50
the taxpayer code first 3 numbers refer to the city district, the next 3 to the block within the district, and the next 4 can refer to the lot in a block if the condo number is 00-0, or to an apartment, or store, etc if the condo number is different than 00-0, in which case all equal condo numbers refer to the same lot within the block.
what I want to do is pass a list of "taxpayer_code" and get the "lot_area" and "built_area" for the lots. the problem is, if the person lives in a condo, her apartment is a fraction of the total built area for the lot. So, if I search for code 0010030078% (the -X number doesn't matter) the result is:
Lot Area = 143 and Built Area = 130
But if I search for 0010030080%, the result I expect is:
Lot Area = 283 and Built Area 155
And if I search for 0010030078%, 0010030079%, the result:
Lot Area = 426 and Built Area 285
So the database should get the taxpayer codes, then look if the condominium number is different from 00-0 for each code passed, if so, it should add to the sum all the other taxpayer codes that share the same condo number within the same district and block. (ideally, if tax codes belonging to different districts or blocks are passed a warning should be returned, and if more tax codes are added to the sum, a listing with all codes added would be nice, but it's okay if that's too much of a hassle!).
I am new to SQL and can't wrap my head around this, I appreciate every help you can give me, thanks!
Hmmm . . . use a subquery and window functions to add up the values that you want:
select ti.*
from (select ti.*,
(case when condominium_num <> '00-0'
then sum(built_area) over (partition by condominium_num)
else built_area
end) as real_built_area
from tax_info ti
) ti
where . . .
I am sure this question has been asked before, but I'm so new to SQL, I can't even combine the correct search terms to find an answer! So, apologies if this is a repetition.
The db I'm creating has to be created at run-time, then the data is entered after creation. Some fields will have a varying number of entries, but the number is unknown at creation time.
I'm struggling to come up with a db design to handle this variation.
As an (anonymised) example, please see below:
| salad_name | salad_type | salad_ingredients | salad_cost |
| apple | fruity | apple | cheap |
| unlikely | meaty | sausages, chorizo | expensive |
| normal | standard | leaves, cucumber, tomatoes | mid |
As you can see, the contents of "salad_ingredients" varies.
My thoughts were:
just enter a single, comma-separated string and separate at run-time. Seems hacky, and couldn't search by salad_ingredients!
have another table, for each salad, such as "apple_ingredients", which could have a varying number of rows for each ingredient. However, I can't do this, because I don't know the salad_name at creation time! :(
Have a separate salad_ingredients table, where each row is a salad_name, and there is an arbitrary number of ingredients fields, say 10, so you could have up to 10 ingredients. Again, seems slightly hacky, as I don't like to unused fields, and what happens if a super-complicated salad comes along?
Is there a solution that I've missed?
Thanks,
Dan
based on my experience the best solution is based on a normalized set of tables
table salads
id
salad_name
salad_type
salad_cost
.
table ingredients
id
name
and
table salad_ingredients
id
id_salad
id_ingredients
where id_salad is the corresponding if from salads
and id_ingredients is the corresponding if from ingredients
using proper join you can get (select) and filter (where) all the values you need
I have a request where I need to create an integrity report where I am looking at sales data and verifying that the payment terms are consistent on all items (rows).
Sample data:
Sales # | Line # | Terms Code
100 | 1.0 | N90
100 | 2.0 | N90
101 | 1.0 | N60
101 | 2.0 | P45
101 | 3.0 | N60
Notice that on SO 101, line 2.0 has a different terms code. I need to detect that and only display order 101 on the report.
I was looking at using the PREVIOUS operator in a variable like this:
=If(Previous([Payment Terms Code])=[Payment Terms Code]) Then 0 Else 1
but that looks at the Order 100 line 2.0 and would flag it incorrectly.
I am not sure how I can do this, but maybe using the IN operator some how. Suggestions?
So is appropriate to describe the requirement as you need to see any Sales Orders that have more than one distinct terms code? If so, you can accomplish it like this:
Create a new variable:
Terms Count =Count([Terms Code]) in ([Sales #])
Add this object to the report. You should see "1" for all of the 100 records, and "2" for the 101 records.
Finally, add a filter to the report on Trans Count > 1.
The syntax for the Previous() function is:
Previous(dimension|measure|Self [;Row|col][;(reset_dims)][;offset][;NoNull])
The third parameter, reset_dims allows you to specify when the list of dimensions used to reset the calculation.
Thus, your formula would then be:
Previous([Payment Terms Code]; ([Sales #];[Line #]))
Notes:
You must always place dimensions in parentheses even if there is only one dimension in the list of reset dimensions.
When you specify a set of reset dimensions you must separate them with semi-colon
I have an Access crosstab query that displays the following results:
| SHORE_TYPE | Total Miles | Class 1 | Class 2 | Class 4 |
| ONSHORE | 31.37 | 0.337121212121212 | 12.4617424242424 | 0 |
I'd like it to display the following results instead. Note the 'Class' columns here show two decimal places:
| SHORE_TYPE | Total Miles | Class 1 | Class 2 | Class 4 |
| ONSHORE | 31.37 | 0.34 | 12.46 | 0.00 |
I've been able to configure the 'Total Miles' column by changing the Format and Decimal Places properties (in the Design View) to "Fixed" and "2," respectively. However, the query column (in Design View) that determines the value in the Class column has only a Format property, which I set to "Fixed"; there is not a Decimal Places property for me to adjust.
I have some similar crosstab queries that are showing the results in the way I desire, but I can't determine any differences between this one and those. Also, I've sometimes seen some of my queries display it the wrong way one time, then the desired way the next time.
This makes me wonder if the problem is a bug in Access, or if there is a something implicitly defined in my code that I should explicitly define.
Here is my SQL:
TRANSFORM IIf(IsNull(Sum([qryPartL].[MILES_OF_PHYS_LENGTH])),0,
Sum([qryPartL].[MILES_OF_PHYS_LENGTH])) AS SumOfMILES_OF_PHYS_LENGTH
SELECT qryPartL.SHORE_TYPE, Sum(qryPartL.MILES_OF_PHYS_LENGTH) AS [Total Miles]
FROM qryPartL
GROUP BY qryPartL.SHORE_TYPE
PIVOT qryPartL.CLASS_LOC_text In ("Class 1","Class 2","Class 4");
EDIT:
After closing and re-opening this query, the Total Miles column is now displaying 31.3714015..., and the properties I had previously set for this column in the Design View are now blank. So, it looks like Access does not consistently save these property settings. At least not in the context in which I was using them.
The trick is to use a series of nested functions.
CDbl: Converts the data to a Double number data type
FormatNumber: Returns an expression formatted as a number with a specified precision (2)
Nz: Returns the specified value (0) when a field is null
The CDbl function won't work if a value is Null.
I also removed the IIf function from the TRANSFORM clause since Nz works better in this case.
Here is the new SQL that returns the desired results. (I've added new lines and indents to make it easier to read. This is a not necessary step, and may in fact not be remembered by Access.)
TRANSFORM
CDbl(
FormatNumber(
Nz(
Sum([qryPartL].[MILES_OF_PHYS_LENGTH])
,0)
,2)
) AS SumOfMILES_OF_PHYS_LENGTH
SELECT qryPartL.SHORE_TYPE,
CDbl(
FormatNumber(
Nz(
Sum(qryPartL.MILES_OF_PHYS_LENGTH)
,0)
,2)
) AS [Total Miles]
FROM qryPartL
GROUP BY qryPartL.SHORE_TYPE
PIVOT qryPartL.CLASS_LOC_text In ("Class 1","Class 2","Class 4");
Thanks to Allen Browne and a tip on his awesome Access website for leading me to this answer.