I have a Label set up in Jaspersoft Studio that references a data adapter file in CSV format. The csv file contains thousands of records. I want the end user to be able to select or key enter the "order no" for the specific records to print. If one order no is entered - record is found and printed. If ten order no's are entered - 10 records will print.
Thank You.
You could use Parameters to let user make input. But because CSV is not query language, you can use Field Expression in Data Source
Here's how to add Parameter
https://community.jaspersoft.com/wiki/using-report-parameters
And this is how to use Field Expression
https://community.jaspersoft.com/wiki/how-apply-parameters-csv-data-source
Detail: Filter by attribute:
In query dialog, you select Filter Expression tab and fill the field with code like this
$F{order_no}.equals($P{order_no})
This code will filter the csv row that has order_no field that equal to order_no parameters
Filter by multiple order_no:
JasperReport are allowed user to do some scripting in Java or Groovy (depending or their settings). So you can do more complicated task like split input into array and use it to search rows.
What I have in mind, are ask end user to seperate order_no by space and use this script to filter the data.
Arrays.asList($P{order_no}.split(" ")).indexOf($F{order_no}) > -1
I have not tested this code yet, but hopefully you get the idea. (Experiment with the script).
Related
I have an excel sheet with many tabs. Say one is called wsMain and the other is called wsDate.
In my data flow transformation I am able to successfully load the data from wsMain to my table.
Now I have to update this transformation where I have to fetch the maximum date from the worksheet wsDate and only load data from wsMain where the date is less than on equal to the maximum date in wsDate (that is the only column available).
So for I have figured out that I need to create a new Excel connection manager to read the data from wsDate and I have used the Aggregate transformatioin to get the maximum date.
Now the question is how do I use this date to restrict the rows coming from wsMain?
I understand from the link below that you can store the value in a variable but what do I do next?:
SSIS set result set from data flow to variable
I have tried using a merge join but not sure if I am doing it right.
Here is what it looks like now:
I could not achieve the above but would be interested to know if that is possible. As a work around I have created a separate dataflow where I have stored the valued in a variable and then used the variable in the conditional split to filter the required rows:
Here is a step by step guide I followed to write the variable:
https://www.proteanit.com/2008/12/11/ssis-writing-to-a-package-variable-in-a-dataflow/
You can obtain the maximum value of the wsDate column first, this use this as a filter to avoid introducing unnecessary records into the data flow which which would be discarded by the Conditional Split. An overview of this process is below. I'd also recommend confirming the data types for all columns involved.
Create an SSIS DateTime variable and name this something descriptive such as MaxDate.
Create a Data Flow Task before the current one with an Excel Source component. Use the SQL command option for the Data Access Mode and enter a SQL statement to return the max value of the wsDate column. In the following example ExcelSource is the name of the sheet that you're pulling from. I'd suggested confirming the query with the Preview button on the Excel Source as well.
Add a Script Component (not Task) after the Excel Source. Add the MaxDate variable in the ReadWriteVariables field on the main page of the Script Component. On the Inputs and Outputs pane add the output column from the Excel Source as an Input Column with the ReadOnly usage Type. Example C# code for this is below. Note that variables can only be written to in the PostExecute method. The Input0_ProcessInputRow method is called once for each row that passes through, however there will only be the single row in this case. On the following code MaxExcelDate is the name of the output column from the Excel Source.
On the Excel Source component in the Data Flow Task where the records are imported from Excel, change the Data Access Mode to SQL command and enter a SQL statement to return records that have a date less than or equal to the maximum wsDate value. This is the last example and the ? is a placeholder for the parameter. After entering this SQL, click the Parameters button and select Parameter0 for the Parameters field, the MaxDate variable for Variables field, and a direction of Input. The Conditional Split can then be removed since these records will now be filtered out.
Excel MAX wsDate SELECT:
SELECT MAX(wsDate) AS MaxExcelDate FROM ExcelSource
C# Script Component:
DateTime maxDate;
public override void PostExecute()
{
base.PostExecute();
Variables.MaxDate = maxDate;
}
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
maxDate = Row.MaxExcelDate;
}
Excel Command with Date Filter:
SELECT
Column1,
Column2,
Column3
FROM ExcelSheet
WHERE DateColumn <= ?
Yes, it is possible. In the data flow, you will need to determine the max date, which you already have. Next, you will need to MERGE JOIN the two data flows on the date column. From there, you will feed it into a CONDITIONAL SPLIT and split where the date columns match [i.e., !ISNULL()] versus do not match [i.e., ISNULL()]. In your case, you only want the matches. The non-matches will be disregarded.
Note: if you use an INNER JOIN on the MERGE JOIN where there is only one date (i.e., MaxDate) to join on, then this will take care of the row filtering for you. You will not need a CONDITIONAL SPLIT.
Welcome to ETL.
Update
It is a real pain that SSIS's MERGE JOINs only perform joins on EQUAL operations as opposed to LESS THAN and GREATER THAN operations. You will need to separate the data flows.
Use a script component to scan the excel file for the MAX Date and assign that value to a package variable in SSIS. Alternatively, you can have a dates table in SQL Server and then use an Execute SQL Command in SSIS to retrieve the MAX Date from the table and assign that value to a package variable
Modify your existing data flow to remove the reading of the Excel date file completely. Then add a DERIVED COLUMN transformation and add a new column that is mapped to the package variable in SSIS that stores the MAX date. You can name the Derived Column Name 'MaxDate'
Add a conditional split transformation with the following CONDITION logic: [AsOfDt] <= [MaxDate]
Set the Output Name to Insert Records
Note: The CONDITIONAL SPLIT creates a new output data flow with restricted/filtered rows. It does not create a new column within the existing data flow. Think of this as a transposition of data flow output from column modification to row modification. Only those rows that match the condition will be sent to the output that you desire. I assume you only want to Insert these records, so I named it that. You can choose whatever naming convention you prefer
Note 2: Sorry for not making the Update my original answer - I haven't used the AGGREGATE transformation before so I was not aware that it restricts row output as opposed to reading a value in the data flow and then assigning it to a variable. That would be a terrific transformation for Microsoft to add to SSIS. It appears that the ROWCOUNT and SCRIPT COMPONENT transformations are the only ones that have the ability to set a package variable value within the data flow.
In my main report I get a (small) list of string values from the data base. I then want to use this list for selecting records in a subreport, along with other input parameters:
The user shall be able to select records based on a range of begin and end date -- this is easy using an input parameter of type java.util.Date with "Is For Prompting" set to true. Another criteria shall be one or more items from a list showing values from a data base field. I could define the list in the report template, but then I'd have hard-coded strings (filled from the data base, but at definition time only).
Now the dilemma is: If I define the input parameters in the main report, I cannot get the values for the list beforehand; if I define them in the subreport, I get no prompt at all, so there's no way to set any of them.
So the report requires values for start and end date, and a list of string values to select from (multiple itmes can be selected). This list shall be built from values from the data base. In the subreport all these values shall be joined into a filter for the records. A user shall be able to define the dates and select items from the list manually before executing the report.
Is there a way to achieve this?
After some more hours of trial & error, and some more research, of course, I found that the keyword is "Query-based Input Controls". This documentation describes their creation on the JasperReports Server. Such input controls can be edited in Jaspersoft Studio as well, however, they actually work on the server only. Anyway, this is the solution to my problem.
At the end of importing a .txt file through the help of the wizard i get a message that some elements were not imported correctly. I have a column in the .txt which should contain dates, but for some reason when i select the column containing dates, and i set its type to date and time, for some reason access cannot recognize them as dates. I'm thinking that it's because of the language difference. I use dates like: 1.1.2011, whereas access uses 1/1/2011.
Where can i change the format?
You can in the Advanced section of the Import Wizard.
If that doesn't work, don't import but link the file and specify the date field as text.
Then create a simple select query where you use the linked table as source. Select all the fields you need.
For the date field, use this expression:
TrueDate: CDate(Replace([YourTextDateField], ".", "/"))
Clean up other fields as well.
Now use this query for the further processing of the data.
Question: Is there a way to build an export order while performing a script? I would prefer a FileMaker-native or FileMaker-called AppleScript solution, if one is possible.
Project: The project is a reporting tool which summarizes sales information (units, price, cost) by user-selectable criteria such as: week, quarter, year, location, product, supplier, etc. I would like a way to specify, at runtime, an export based on the user-selected criteria.
Example: If a user selected units sold summarized by supplier per quarter I would like to be able to have the script select:
Group by:
quarter
supplier
Export Order
quarter
units summary by quarter
supplier
units summary by supplier
There are obviously many permutations, so setting up an export for each individual export for each set of options is infeasible.
If the target format is text-based (i.e. tab- or comma-separated), then I'd export to XML and write a XSLT to summarize it as necessary. To pass parameters to the XSLT I normally export a small XML file to the same folder.
A solution I can think of is to export calculations rather than the original fields. With the example you give, assume that the user can export up to two fields. You create two calculation fields and two text fields. The text fields store the name of the field to export and the calculation fields use Evaluate (or GetField) to get the contents of the fields. It gets complicated if you're also exporting date and time fields, but it's still workable. If you need to include the field names in the export, you create an extra record and work your calculations for that record to contain the names of the fields the user has selected.
Not trivial, but still possible.
Building on Mikhail's and Chuck's suggestions, I think the best method for this particular project is going to be to build the contents of a .csv in a global field and then Export Field Contents. The basic outline of what I'm doing:
Go to the first record
Loop
WriteTheRows (see below), comma delimited, to a global field
Set $thisGroup to the count of records summarized by this summary field
Exit Loop If Get (CurrentRecord) + $thisGroup >= Get (FoundCount)
Go to record [Get (CurrentRecord) + $thisGroup]
End Loop
Export Field Contents [global field]
WriteTheRows is a custom function that does the following:
The output I'm trying to write can be sorted by up to 7 different criteria at the same time (for example: I could summarize supplier sales by quarter or I could summarize quarter sales by supplier)
Compare the highest level sort field's value to the last value we found for the highest level sort field.
If they're different WriteALine to the global field for this sort field, the next sort field, all sort fields down to the lowest level.
If they're the same, compare the (highest level sort field - 1) to the stored value for the (highest level sort field - 1)
If they're the same, WriteALine to the global field for the (highest level sort field - 1) on down to the lowest level sort field
... repeat until we're down to the lowest sort field
WriteALine is another custom function which adds the appropriate labels, commas and values using the GetSummary ( revenueSummary ; Evaluate ( "summaryField" & summaryFieldNumber ) as Chuck suggests in his answer.
I am trying to write/learn a simple Perl parser for some CSV files that I have and I need some help.
In a directory I have a series of date-indexed CSV files in the form of Text-Date.csv. The date is in the form of Month-DD-YYYY (ex., January-07-2011). For each weekday there is a CSV file generated.
The Perl script should open each file look for a particular row that matches a user-entered criteria and return that row. Each row is stock price data with different stocks in different rows. What the script should do is return the price of a particular stock (ex., IBM) across all dates that CSVs are generated.
I have the parser working for a specific CSV/date that I choose, but I want to be able to pluck out the row in all CSVs. Also when I print the IBM price for each dated CSV I want to display the date next to the price (ex., January-07-2011 IBM 147.93).
Can you help me get this done?
If your question is how to crawl a bunch of files and run some function on each one, you probably want File::Find. To parse CSV, definitely use Text::xSV and not a custom parser. There is more to parsing CSV than calling split(",").
To parse CSV files, use the Text::CSV module.
It is more complex to decide how you are going to apply the criteria - you'll need to determine what the user specifies and work out how to translate that into Perl code that evaluates the condition correctly.