Tabulator combine multiple tables in a single pdf - javascript

I am using http://tabulator.info/ to generate multiple tables on a single HTML document page.
When I am triggering the pdf-download via the button, a pdf document should get generated that includes the tables from the document.
So far, downloading a single table works, but I don't know how I could potentially add more tables to the document before jsPDF finishes.
What I have tried out so far is that I grabbed the lastTable1 = doc.lastAutoTable object inside the documentProcessing function when triggering a download for table1. The plan is to pass it into table2.download() and add it via autoTable: function(doc){doc.autoTable(lastTable1)}.
While I do grab an object with this approach, I can not use it to reconstruct the autotable object (e.g. doc.autoTable(lastTable1) does not produce the same table again).
I have prepared a simple jsfiddle where I generate two tables and a download button. Just to illustrate that the reconstruction of the autotable object does not work, I have added it once more to the doc before creating the pdf.

There is no built in way for tabulator to do this.
But the good news is that it should be easy to add something to handle this yourself.
This Issue shows how you can use jsPDF to merge to PDFs into the same document.
You could use the downloadReady callback built into tabulator to intercept the PDF file created from each table and then combine them using the method outlined in the above issue
var table = new Tabulator("#example-table", {
downloadReady:function(fileContents, blob){
//fileContents - the unencoded contents of the file
//blob - the blob object for the download
mergeWithPreviousPDFs(blob); // call a function based on the previous issue that merges the new PDF with the previous PDF's
return blob; //must return a blob to proceed with the download, return false to abort download
}
});
if you return false from this callback the download will not be triggered, so you can intercept the PDF output on all but the final table to prevent download and then return the combined output from the last table to trigger the download.

Related

Generate Table/Grid from script in Adobe InDesign

Documentation doesn't help at all,no Table or Grid is specified...(or I cant find it)
I tried to create a grid from inside InDesign and it shows up as TextFrame,but still I dont understand how to manage it.
The tool I need to do takes a file(CSV/JSON) and generates a Table(or whatever is called in Adobe) from it,but the problem is that I can't find anything about Table generation.
Basically you can make a table from a selected text with the method convertToTable() this way:
var doc = app.activeDocument; // your document
var frame = doc.pages[0].textFrames[0]; // first text frame on first page
frame.texts.everyItem().select(); // select all text inside the frame
var table = app.selection[0].convertToTable(); // convert the selection into a table
Before:
After:
Reference:
Text object
As for the rest... it's need more details about your workflow. JSON and CSV are quite different beasts, it would be different parsing algorithms for each of the formats. Will you copy the contents of the files manually or the script should read all csv or json files from some predefined folder? Or there should be some interface to select a file(s). Or a folder? How it supposed to handle a page size and formatting of the table? Etc...

Is there a way to Post an array to web api or mvc controller and get a file back to download as a result?

I use an html table where it's content can be changed with mouse drag and drop implemented. Technically, you can move the data from any table cell to another. The table size 50 row * 10 column with each cell given a unique identifier. I want to export it to .xlsx format with C# EPPlus library, and give back the exported file to client.
So I need the pass the whole table data upon a button press and post it to either a web api or an mvc controller, create an excel file (like the original html table data) and send it back to download with browser.
So the idea is to create an array which contains each of table cell's value ( of course there should be empty cells in that array), and post that array to controller.
The problem with that approach lies in the download, if I call the api or mvc controller with regular jquery's ajax.post it did not recognize the response as a file.
C# code after ajax post:
[HttpPost]
public IHttpActionResult PostSavedReportExcel([FromBody]List<SavedReports> savedReports, [FromUri] string dateid)
{
//some excel creation code
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StreamContent(new MemoryStream(package.GetAsByteArray()))
};
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
FileName = dateid + "_report.xlsx"
};
ResponseMessageResult responseMessageResult = ResponseMessage(response);
return responseMessageResult;
}
Usually, for this kind of result I could use window.location = myurltocontroller to download properly , but that is only for GET requests, POST anything is not possible.
I found some answers which could help me in this topic:
JavaScript post request like a form submit
This points out I should go with creating a form, which passes the values, but I do not know how to do so in case of arrays (the table consists 50*10 = 500 values which I have to pass in the form)
I tried some only frontend solutions to the html-excel export problem, which of course does not require to build files on api side, but free jquery add-ins are deprecated, not customizeable, handle only .xls formats, etc.
I found EPPlus nuget package a highly customizeable tool, that is why I want to try this is at first place.
So the question is: how can I post an array of 500 elements, that the controller will recognize, generate the file, and make it automatically download from browser?
If you can provide some code that would be fantastic, but giving me the right direction is also helpful.
Thank you.
You can use fetch() (docs) to send the request from the JS frontend. When the browser (JS) has received the response, it can then offer its binary content as a download. Something like this:
fetch("http://your-api/convert-to-excel", // Send the POST request to the Backend
{
method:"POST",
body: JSON.stringify(
[[1,2],[3,4]] // Here you can put your matrix
)
})
.then(response => response.blob())
.then(blob => {
// Put the response BLOB into a virtual download from JS
if (navigator.appVersion.toString().indexOf('.NET') > 0) {
window.navigator.msSaveBlob(blob, "my-excel-export.xlsx");
} else {
var a = window.document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = "my-excel-export.xlsx";
a.click();
}});
So the JS part of the browser actually first downloads the file behind the scenes, and only when it's done, it's triggering the "download" from the browsers memory into a file on the HD.
This is a quite common scenario with REST APIs that require bearer token authentication.

How to choose where to append data?

How do I choose where to append data with fs.appendFileSync()?
My current code:
var fd = fs.openSync('test.js', 'a');
fs.appendFileSync('test.js', "/**/");
fs.closeSync(fd);
This just appends the data at the end of the file. The options object gives me no way to choose where to append it.
fs.appendFileSync() can only append data to the end of the file. It does not have the option you are asking for.
In fact, the only way (with a normal file system) to insert data into the middle of a file is to rewrite data that is in the file to move it later in the file and then write to the block where you want the new data to go. For this, you would use fs.read() and fs.write() passing it the desired file positions.

Using Jquery methods on Data Returned from Ajax, with out printing out the data

So I have a rather unique situation. I am using JQuery to gather some data based on two date ranges, what is returned as a response in the $data variable (I am using Ajax) I have set, is a html table.
Now I don't want the user to ever see this table, I want to use This jquery plugin to download the CSV file of that table. The question is, if the table sits inside of a $data and can be seen via the network tab in Chrom Dev Tools, under Response, is it possible to be manipulated with Jquery?
In our inhouse framework, we do the following to get Ajax Data:
// The following belongs to a JS class method.
data = {
startDate : $('.startDate').val(),
endDate : $('.endDate').val()
}
CT.postSynch('report/payRollReport/downloadPayRoleReport', {data : data}, function(data){
console.log(data);
});
We pass a data object to our Ajax wrapper, call a controller with an action (in this case downloadPayRoleReport translates to ajaxDownloadPayRoleReport()) which in turn returns an HTML table, which I can view via console.log(data)
I want to use the above linked plugin on data to then turn this html table into a csv and instant download.
Question is, can this be done?
You can create a jQuery object from the table. Then you can do anything to the jQuery object just like you could if it were actually on the DOM. You can always put the table on the DOM as well off screen, but I think any chance you have to not touch the DOM you should take it.
var myTable = $(data);
myTable.mySpecialTableMethodToExportToCSV();

Create a textfile from the input of an html-form with the browser (client-side)

I have an html site with a form in it and I want the user to be able to create a text/xml file depending on the input. But I wan't to avoid setting up a webserver only for this task.
Is there a good way, to do that, e.g. with Javascript? I think you can't create files with Javascript, but maybe create a data url and pass the text, so the user can save it to file?
Or is there another way to achieve this simple task without a webserver?
Solved it, somehow. I create a data url data:text/xml;charset=utf-8, followed by the XML.
function createXML() {
var XML = 'data:text/xml;charset=utf-8,<MainNode>';
var elements = document.getElementsByTagName('input'),i;
for (i in elements) {
if (elements[i].checked == true) {
XML += elements[i].value;
}
}
XML += '</MainNode>';
window.open(XML);
}
So the url looks like data:text/xml;charset=utf-8,<MainNode><SubNode>...</SubNode>...</MainNode>
Unfortunately this doesn't work for me on Chromium(Chrome) and on Firefox. It just displays the XML instead of showing a save dialog. But I think that's because of my settings and at least you can save it as a XML-file manually.
I haven't tried this but it should work.
After getting form data, system will call page A.
page A will have javascript that gets query strings and builds the page accordingly.
After finishing page build, user can save current page with following statement in javascript
document.execCommand('SaveAs',true,'file.html');

Categories