I have several Birt Reports that I am trying to set up to run on a cron job that will email pdfs of the reports every morning. Everything is working fine as far as the generation and emailing goes; the only issue I am stuck with is this: if there is nothing to report, a pdf with just the report title is generated and emailed (a blank report, basically). I'd like to stop this report from being generated at all, so i can skip the emailing, if the pdf file does not exist.
I have been all over Google for two days now, and the closest I can find is this: http://www.eclipse.org/forums/index.php/t/458779/ in which someone was trying to solve a similar problem and received a push in the right direction, but not a complete solution.
It appears as if this can be done during the beforerender script... but how?
I know I need to:
set a persistent global variable in the oncreate if there is indeed data to report.
get the persistent global variable in the beforerender script.
send the magic don't generate report command.
I'm doing all of generating and emailing from a php script, not Java, so I can't send commands like IEngineTask.cancel() (or can I???)
Yes, I know I can make a row in the report that says "No data to report", but that's not what my users want.
And yes, I could query the database outside of the report to determine if there is valid data to report or not, but i'd prefer not to.
And maybe I could even open and read the pdf, programmatically to see if there is anything there, but that sounds like more of a hassle than it's worth...
So, how do I do this?
Thanks.
My answer is a little bit late, but I'm doing it like this in a framework that is working for hundreds of reports, probably it could be simplified for a single report:
Note that all the code is written from memory (not copied from our framework), so maybe it contains some errors.
Add an external Javascript file myframework.js to your report.
In this file, define an object myframework like this:
if (myframework == undefined) {
myframework = {
dataFound: false,
afterReport: function() {
// Write it to the appContext.
// Using Java, you could read it after the
// runAndRenderTask is done.
reportContext.getAppContext().put("dataFound", this.dataFound);
// But since you probably cannot the context
// (don't like coding Java?), the report has to
// tell it to he world some other way...
var txt = "dataFound=" + (dataFound? "true": "false");
var fw = new java.io.FileWriter("c:\\reportcontext.out");
fw.write(txt);
fw.close();
}
};
}
Add the JS file to your report's resources.
In your report, at a place where you decide that the report has found something (e.g. typically in a data set's onFetch event), tell the framework so by calling
myframework.dataFound = true;
In the reports's afterFactory or afterRender event, call
myframework.afterReport();
Then your report should create an output file c:\reportcontext.out which contains the information you need.
Related
I tried to find it on StackOverflow and also tried to google it, but could not find any relevant answer.
I want to send monthly reports to the user of Laravel application with a PDF that contain a graph/chart.
This is what that is already done
Created a route, lets say
Route::get('/print/', 'PrintController#report');
In printController created a report function that is getting all the necessary data from the DB and returning a view with user data
return view::make('monthly_report', $user_data);
In monthly_report view, get all the user data, show the view and create a chart with the data. The chart is created with Charts.js. it is in a canvas.
Send the generated chart as image to the server with Ajax. For example
var canvas = document.getElementById("myChart"), // Get your canvas
imgdata = canvas.toDataURL();
file_name = "<?php echo $chart_file_name; ?>"; //created with userId and date
//send it to server
$.ajax({
method: "POST",
url: "save",
data: {
data: imgdata,
file_name: file_name,
_token: token,
}
});
Created a save route
Route::post('print/save', 'PrintController#saveChart');
In print controller, saveChart function, save the chart
$data = base64_decode($data);
//save chart on server
file_put_contents("Charts/".$fileName, $data);
Then create a PDF report by using another view monthly_report2, that is also in saveChart function. The view monthly_report2 does not use any JavaScript and use the chart image that was generated by monthly_report, in number 6.
$pdf = \PDF::loadView('monthly_report2', $cll_data);
file_put_contents("reports/".$pdf_name, $pdf->output());
It save the generated PDF on server. So far so good.
To send these PDF reports to the users by e-mail, I will created a schedule/crone job that will be run on a specific date, monthly and will send the e-mails with PDF reports as attachments.
I skip some details for clarity, please ask, if you need more information.
Thank you for reading so far, now I have two questions
The way I am doing is good or it can be improve?
We want all this process automatically (generating reports and sending by email). To generate the PDF's, monthly_report view must be loaded? so that it generate the Chart and send it to the server. Can we schedule it also, so that it generate the pdf reports automatically?, If no, is there any other way to do it?
Kind of a big question, but I'll try to answer
I think it's good. I'm not a big fan of using JavaScript to create charts, but that's me. You obviously know what you're doing and PDF generation is in my experience a "If it works, please don't break it" functionality.
I think this might be more difficult. Since you're using JavaScript to create charts, you need some kind of engine (NodeJS comes to mind) to parse the JavaScript and actually create your charts without opening a browser and doing it manually. (This is why I don't like using JavaScript to create charts). You could take a look at tutorials like this one to get an idea of how to render your charts serverside.
After that, you can take a look at the Laravel task scheduler (provided you're on Laravel 5, a community package exists for Laravel 4). You can schedule existing and custom-made commands to be executed. In pseudo-code, a PDF generation command could look like this:
public function createAndSendCharts() {
// 1. Get necessary user data
// 2. Create your charts
// 3. Save your charts
// 4. Create email with charts
// 5. Send your email
}
You could then add that function to your Task Scheduler
$schedule->command('send:charts')
->monthly();
Hope this was of some help. All in all, you're doing fine, but the choice for ChartJS has some consequences if you want to automate the whole process. Nothing really special, tons of tutorials exist for this situation :)
I'm having trouble with CodeMirror. I'm trying to add in live number scrubbing, similar to Brett Victor's example, and Khan Academy's capability, but I am not having too much luck.
I can't post links, but I found this library which kind of gets the job done (made by user FWeinb on GitHub) which can kind of accomplish what I'm looking for, but I've noticed that although the numbers appear to have been changed, as soon as I do something like press enter in CodeMirror, then the value of the variable resets to what it was originally.
I'm using ReactJS, and I am not too sure how to fix this. I'm trying something a little ludicrous by calling this.replaceRange every time the contents are being changed, but there must be a better way. Here is a snippet of my code. It's not what I want it to be ideally, but just for testing purposes:
this.cm.on('dblclick', this.handleDblClick.bind(this))
...
handleDblClick() {
let matches = document.querySelectorAll(".cm-number");
let scrub = new Scrubbing (matches[0],
{ driver :
[
Scrubbing.driver.Mouse,
Scrubbing.driver.MouseWheel,
Scrubbing.driver.Touch
]
})
matches[0].addEventListener('DOMSubtreeModified', () => {
//console.log('change detected')
})
}
So I know that currently the scrubber edits this: <span class="cm-number"></span>, but that the actual underlying data isn't updating with the scrubber, nor is it persisting. Can anyone shed some light on what I should be doing here so that the value of the variable within the editor is updating live with the scrubber, and so that the value persists upon a new action?
I would like to display some info on the screen ... which will disappear.
Example : an Uiview is displayed for the first time to an user (or feature never used by the user). I would like to display on a screen a label or an image to explain how to use this new feature. After that it will disappear ...
If this functionality has already been used by the user, the message is ofcourse not displayed.
example of message --> to add a gamer, press +
How to do that ? a lot of apps have this kind of help.
thanks
What you have to do is actually very simple : have a persistent variable, and change its value. Each time the user could see the help popup, you check the value of the variable you stored persistently. If this variable indicates that the user have already seen the help, you don't display it again. Otherwise, you show it. Simple example:
let helpSeen: Bool = getVarFromPersistent()
if helpSeen == false {
// DISPLAY THE HELP MESSAGE OR POPUP
setHelpSeenVar(true)
}
Where getVarFromPersistent() and setHelpSeenVar() are function you could create to respectively retrieve the variable from the persistent data and set the variable in the persistent data.
Now, you have to figure out how to use persistent data. You can have a look at CoreData, that is provided by Apple and "ready to use" in Xcode. You've probably already seen the use core data tickbox when you create a project.
Third party libraries exists as well like RealmSwift, who reached version 1.0 recently.
I'm not an expert, but I think Realm is simpler to use than Core Data. The technology used by the two libraries could be different though, maybe someone else could tell you more about it. Anyway, you will find a lot of article about Realm and Core Data on Google.
As a novice with workflows I create a workflow (in VS2010 workflow designer) with a sequence within which I have a writeline activity. I am experimenting with creating arguments for the workflow so I create 2 arguments in the argument pane w/o doing anything with them at the activity level. (Noteworthy that I dont have a grasp of how to use arguments in the workflow yet). However I save my workflow while the workflow does not show any visible errors( red circles with an excalmation mark). Next time I open the workflow I get the error :
Workflow Designer encountered problems with your document .
Please check the document for invalid content, namespaces,references, or reference loops.
And that seems so final because there is no way that I can have access to my original workflow to possibly correct my error (whatever they might be). when I click on the detail down arrow I see this: Could not find member 'a' in type _8684 .
a is one of the two int32 arguments that I had in the workflow but which I never used in any of the activities.
I would appreciate any help. Thanks in advance.
It seems you're trying to re-host your Workflow Designer and it's not generating correct XAML for you.
The error Could not find member <mname> in type <tname> commonly occurs if the Workflow Designer instance is directly loading a container activity (sequence, flowchart etc.) instead of using an ActivityBuilder first.
If you're already using an ActivityBuilder then you may have missed giving it the root activity namespace. The correct way to add System.Activities.Presentation.WorkflowDesigner is:
this.workflowDesigner = new WorkflowDesigner();
this.workflowDesigner.Load(new ActivityBuilder { Implementation = new Sequence(),
Name = "RootNamespace.RootActivity" });
With the Name set properly WF designer would stop using random types (like _8684 in your case) and generate correct XAML on save/serialization. This should help you get rid of the namespace errors.
I have a results page and I am trying to work out how to auto update the page when an external database field is updated. I have seen quite a few examples but they seem to relate to PHP. I have a test that calls various APIs that can take up to an hour to complete. Once the test has completed, it will enter a success or failed message in a database field.
I already have my results page being rendered by django using template tags. I have a table and I have the field I would like to update. There are multiple fields that need update which correspond to each API test.
I have seen this site.. is this the kind of stuff to use? http://www.dajaxproject.com/ Is this an easy task to do? Does anyone have any ideas on how to do this?
Sorry but I don't know where to start on this one.
Cheers - Oli
I decided not to be so bold and just use the old classic page update for this purpose using javascript..
window.onload = setupRefresh;
function setupRefresh() {
setTimeout("refreshPage();", 30000); // milliseconds
}
function refreshPage() {
window.location = location.href;
}
Still open for options however I'm rather inexperienced in django and maybe this was too much to bite off too quickly..