I have an issue where I'm trying to export html table to a csv file. The issue is that no download box appears but I know my JS function is run via an alert check.
I wonder if it can be my table that is generated from an exiting csv file like this:
echo "<table>\n\n";
$f = fopen("../translations/EXAMPLE.csv", "r");
while (($line = fgetcsv($f)) !== false) {
echo "<tr>";
foreach ($line as $cell) {
echo "<td contenteditable>" . htmlspecialchars($cell) . "</td>";
}
echo "</tr>\n";
}
fclose($f);
echo "\n</table>";
I have a button to call the javascript:
<button class='saveCSV' style='float:right;'>Save</button>
And here is the javascript file:
$(document).ready(function () {
function exportTableToCSV($table, filename) {
var $rows = $table.find('tr:has(td)'),
// Temporary delimiter characters unlikely to be typed by keyboard
// This is to avoid accidentally splitting the actual contents
tmpColDelim = String.fromCharCode(11), // vertical tab character
tmpRowDelim = String.fromCharCode(0), // null character
// actual delimiter characters for CSV format
colDelim = '","',
rowDelim = '"\r\n"',
// Grab text from table into CSV formatted string
csv = '"' + $rows.map(function (i, row) {
var $row = $(row),
$cols = $row.find('td');
return $cols.map(function (j, col) {
var $col = $(col),
text = $col.text();
return text.replace(/"/g, '""'); // escape double quotes
}).get().join(tmpColDelim);
}).get().join(tmpRowDelim)
.split(tmpRowDelim).join(rowDelim)
.split(tmpColDelim).join(colDelim) + '"',
// Data URI
csvData = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csv);
$(this)
.attr({
'download': filename,
'href': csvData,
'target': '_blank'
});
alert("KØRT");
}
// This must be a hyperlink
$(".saveCSV").on('click', function (event) {
// CSV
exportTableToCSV.apply(this, [$('#dvData>table'), 'export.csv']);
// IF CSV, don't do event.preventDefault() or return false
// We actually need this to be a typical hyperlink
});
});
Anyone having an idea to what os wrong here and the csv file is not exported?
Simply convert the csvData to a blob file or base64 file and then send to the server using ajax. Take note of the two functions added after the document.ready.
$(document).ready(function () {
function dataURItoBlob(dataURI) {
// convert base64/URLEncoded data component to raw binary data held in a string
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
}
function uploadCSV( blob ) {
var reader = new FileReader();
reader.onload = function(event){
var fd = {};
fd["fname"] = "example.csv";
fd["data"] = event.target.result;
$.ajax({
type: 'POST',
url: 'upload.php',
data: fd,
dataType: 'text'
}).done(function(data) {
console.log(data);
});
};
reader.readAsDataURL(blob);
}
function exportTableToCSV($table, filename) {
var $rows = $table.find('tr:has(td)'),
// Temporary delimiter characters unlikely to be typed by keyboard
// This is to avoid accidentally splitting the actual contents
tmpColDelim = String.fromCharCode(11), // vertical tab character
tmpRowDelim = String.fromCharCode(0), // null character
// actual delimiter characters for CSV format
colDelim = '","',
rowDelim = '"\r\n"',
// Grab text from table into CSV formatted string
csv = '"' + $rows.map(function (i, row) {
var $row = $(row),
$cols = $row.find('td');
return $cols.map(function (j, col) {
var $col = $(col),
text = $col.text();
return text.replace(/"/g, '""'); // escape double quotes
}).get().join(tmpColDelim);
}).get().join(tmpRowDelim)
.split(tmpRowDelim).join(rowDelim)
.split(tmpColDelim).join(colDelim) + '"',
// Data URI
csvData = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csv);
var asblob = dataURItoBlob(csvData);
uploadCSV( asblob ); //prepare and send via ajax post. The ajax post is not tested though
}
// This must be a hyperlink
$(".saveCSV").on('click', function (event) {
// CSV
exportTableToCSV.apply(this, [$('#dvData>table'), 'export.csv']);
// IF CSV, don't do event.preventDefault() or return false
// We actually need this to be a typical hyperlink
});
});
PHP CODE should be
<?
// pull the raw binary data from the POST array
$data = substr($_POST['data'], strpos($_POST['data'], ",") + 1);
// decode it
$decodedData = base64_decode($data);
// print out the raw data,
$filename = $_POST['fname'];
echo $filename;
// write the data out to the file
$fp = fopen($filename, 'wb');
fwrite($fp, $decodedData);
fclose($fp);
?>
OR
Blob blob = *// get Blob file *
byte [] bytes = blob.getBytes(1, (int) blob.length());
Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Testing/";
File dir = new File(filePath);
File file = new File(dir, "filename.csv");
FileOutputStream fOut = new FileOutputStream(file);
//bmp.compress(Bitmap.CompressFormat.PNG, 85, fOut);
fOut.flush();
fOut.close();
Have you tried removing the encodeURIComponent method? With some initial testing, I found this to break functionality. So your code may look something like this instead:
var csvData = 'data:application/csv;charset=utf-8,' + csv;
Here's an example of this in action.
Remember also, that what you're attempting to do won't work in every browser as the download attribute is not universally supported. See here for more about support.
Related
I am exporting WooCommerce orders to a google sheets using WooCommerce Webhooks and Apps Script
I have two queires
1) How do I reference WooCommerce "add-ons" data
2) Parent order ID is not showing in google sheet
function doPost(e) {
var myData = JSON.parse([e.postData.contents]);
var timestamp = new Date();
var order_number = myData.number;
var parent_id= myData.parent_id;
var order_status = myData.status;
var billing_first_name = myData.billing.first_name;
var billing_last_name = myData.billing.last_name;
var billing_phone = myData.billing.phone;
var billing_email = myData.billing.email;
var order_total = myData.total;
var billing_address_1 = myData.billing.address_1;
var billing_address_2 = myData.billing.address_2;
var billing_city = myData.billing.city;
var billing_address = billing_address_1 + ", " + billing_address_2 + ", " + billing_city;
var billing_postcode = myData.billing.postcode;
var shipping_first_name = myData.shipping.first_name;
var shipping_last_name = myData.shipping.last_name;
var shipping_address_1 = myData.shipping.address_1;
var shipping_address_2 = myData.shipping.address_2;
var shipping_city = myData.shipping.city;
var shipping_address = shipping_address_1 + ", " + shipping_address_2 + ", " + shipping_city;
var shipping_postcode = myData.shipping.postcode;
var lineitems=""
for (i in myData.line_items)
{
var product_name = myData.line_items[i].name;
var itemName = myData.line_items[i].name;
var quantity = myData.line_items[i].quantity;
var linetotal = myData.line_items[i].total;
var product_items = quantity + " x " + itemName + ": £"+linetotal +"\n";
var lineitems =lineitems+product_items;
}
var sheet = SpreadsheetApp.getActiveSheet();
sheet.appendRow([timestamp,order_number,parent_id,order_status,billing_first_name,billing_last_name,billing_phone,billing_email,lineitems,order_total,billing_address,billing_postcode,shipping_first_name,shipping_last_name,shipping_address,shipping_postcode]);
}
What is missing from your question is:
We don't know from from where and how you get the order data in javascript
We don't know where you need to display the order Number.
So we can only make a generic answer.
Also note that asking multiple questions at once is not allowed in StackOverFlow.
1) The WooCommerce add-ons data within an WooCommerce order is stored as order item custom meta data:
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// The loop to get the order items which are WC_Order_Item_Product objects since WC 3+
foreach( $order->get_items() as $item_id => $item ){
// Get the special meta data in an array:
$meta_data = $item->get_meta_data();
echo '<pre>'; print_r($meta_data); echo '<pre>'; // Testing raw output
// Get all additional meta data (formatted in an unprotected array)
$formatted_meta_data = $item->get_formatted_meta_data( ' ', true );
echo '<pre>'; print_r($formatted_meta_data); echo '<pre>'; // Testing raw output
// Get the specific meta data from a meta_key:
$meta_value = $item->get_meta( 'custom_meta_key' );
}
Related: Get Order items and WC_Order_Item_Product in WooCommerce 3
2) To get the parent order number from a subscription you will use:
From the subscription ID we can get the order ID very easily:
$order_id = wp_get_post_parent_id( $subscription_id );
From a WC_Subscription Object we can also get the order ID very easily:
$order_id = $subscription->get_parent_id();
Then from this order ID you can get the order number with:
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
$order_mumber = $order->get_order_number();
or with:
$order_mumber = get_post_meta( $order_id, _order_number, true );
I am trying to export data to excel in Javascript. Below is the code that I used:
var createAndExport = function(data){
var table = "<table><thead><tr><td>";
var head = Object.keys(data[0]);
for(var i=0;i<head.length;i++){
table += head[i]+"</td><td>";
}
table += "</td></tr></thead><tbody>";
for(var i=0;i<data.length;i++){
table += "<tr>";
for(var j=0;j<head.length;j++){
table += "<td>"+data[i][head[j]]+"</td>";
}
table += "</tr>";
}
table += "</tbody></table>";
var uri = 'data:application/vnd.ms-excel;charset=utf-8,'+ table;
var downloadLink = document.createElement("a");
downloadLink.href = uri;
downloadLink.download = "data.xls";
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
}
This code working fine and downloading the data as excel. But the issue is data containing arabic words, that is appearing as some other characters in dowloaded excel as in the image.
How can I fix this issue of arabic words?
The encoding informations needs to be in the HTMLtemplate too:
var createAndExport = function(data){
var table = "<head><meta charset='UTF-8'></head><table><thead><tr><td>";
...
See fiddle: https://jsfiddle.net/3fohpL9u/2/
I have code which return loop from php to ajax via json_encode()
Let me know what I want to do.
there is one table call SMTP. Assume that it has 3 value and I want to fetch that 3 value from table, store in array () and Display it to HTML via AJAX in table format.
So I'm confused where I place my loop, in AJAX or PHP ?
Here is my code.
PHP
$result=mysql_query("select * from ".$db.".smtp WHERE id = '$user' ");
if($result === FALSE) {
die(mysql_error());
}
while($data = mysql_fetch_row($result))
{
$array = array($data[2],$data[3]);
}
echo json_encode($array);
JS
$(document).ready(function() {
GolbalURL = $.session.get('URL');
$.ajax({
type: "GET",
url: GolbalURL+"smtp.php",
dataType: "html",
success: function(response){
$("#divsmtp").html(response);
}
});
});
HTML
<div id = "divsmtp"></div>
This code return only last value. inarray like ["data2","data3"]
My Longest way to do
success: function(response){
resultObj = eval (response);
var i = Object.keys(resultObj).length;
i /=2;
//$("#divsmtp").html(i);
var content = "<table>"
for(j=0; j<i; j++){
k = j+1;
if (j % 2 === 0)
{
alert("j="+j+" k="+k );
content += '<tr><td>' + resultObj[j] + resultObj[k] + '</td></tr>';
}
else
{
k = k+1;
var m = j+1;
alert("m="+m+" k="+k );
content += '<tr><td>' + resultObj[m] + resultObj[k] + '</td></tr>';
}
}
content += "</table>"
$('#divsmtp').append(content);
}
Because you are always overwrite the $array variable with an array.
Use: $array[] = array($data[2], $data[3]);
Use json decoding at jquery end
EDIT Small way
$.each($.parseJSON(response), function( index, value ) {
//Loop using key value LIKE: index => value
});
//Old
success: function(response){
var jsonDecoded = $.parseJSON(response);
console.log(jsonDecoded );
$.each(jsonDecoded, function( index, value ) {
//Loop using key value LIKE: index => value
});
$("#divsmtp").html(response);
}
Create the array on the PHP side like this -
$array = array();
while($data = mysql_fetch_row($result))
{
array_push($array, $data);
}
echo json_encode($array);
Hi I'm trying to get the xml data from php to javascript using DOM document and it keeps giving me : XML or text declaration not at start of entity error.(on firebug)
I tried saving it to a real xml file and it outputs a well formatted xml.
I guess the reason for this is white space on top of the xml file. I tried using ob_start(); and ob_end_flush(); but couldn't get that working
BTW I'm new to Ajax!
JS script
var xh = createRequest();
var xhrObject = false;
if (window.XMLHttpRequest)
{
xHRObject = new XMLHttpRequest();
}
else if (window.ActiveXObject)
{
xHRObject = new ActiveXObject("Microsoft.XMLHTTP");
}
function getData()
{
if ((xh.readyState == 4) &&(xh.status == 200))
{
alert("hi");
var serverResponse = xh.responseXML;
var header = serverResponse.getElementsByTagName("good");
var spantag = document.getElementById("sp");
var x;
spantag.innerHTML = "";
x = "<table cellpadding='1' cellspacing='6' border='0'>";
x += "<tr><td>ID</td><td>price</td><td>quantity</td><td>Total</td><td>Remove</td></tr>";
for (i=0; i<header.length; i++)
{
var id = header[i].getElementsByTagName("ID")[0].childNodes[0].nodeValue;
var price = header[i].getElementsByTagName("price")[0].childNodes[0].nodeValue;
var qty = header[i].getElementsByTagName("quantity")[0].childNodes[0].nodeValue;
var total = header[i].getElementsByTagName("total")[0].childNodes[0].nodeValue;
if(qty=="0")
{
continue;
}
x += "<tr>"
+ "<td>" + id + "</td>"
+ "<td>" + price + "</td>"
+ "<td>" + qty + "</td>"
+ "<td>" + total + "</td>"
+ "<td>" + "<a href='#' onclick='AddRemoveItem(\"Remove\","+id+");'>Remove Item</a>" + "</td>"
+ "</tr>";
}
x += "</table>";
if (header.length != 0)
spantag.innerHTML = x;
}
}
PHP code
function toXml($shop_goods)
{
$doc = new DomDocument();
$goods = $doc->createElement('goods');
$goods = $doc->appendChild($goods);
foreach ($shop_goods as $Item => $ItemName)
{
$good = $doc->createElement('good');
$good = $goods->appendChild($good);
$title = $doc->createElement('ID');
$title = $good->appendChild($title);
$value = $doc->createTextNode($Item);
$value = $title->appendChild($value);
$price = $doc->createElement('price');
$price = $good->appendChild($price);
$value3 = $doc->createTextNode($ItemName["price"]);
$value3 = $price->appendChild($value3);
$quantity = $doc->createElement('quantity');
$quantity = $good->appendChild($quantity);
$value2 = $doc->createTextNode($ItemName["qty"]);
$value2 = $quantity->appendChild($value2);
$total = $doc->createElement('total');
$total = $good->appendChild($total);
$value3 = $doc->createTextNode($ItemName["total"]);
$value3 = $total->appendChild($value3);
}
$strXml = $doc->saveXML();
//echo("<br>----- DATA RECOREDED!!! ----");
return $strXml;
}
As others have noted, this could be an encoding issue.
Check your code for the Xml byte order mark.
Check the document is returning the correct mime type.
Not sure of your constraints but have you considered serializing your data to Json format. It's much easier to work with in the browser.
Finally consider using a library like JQuery to handle your ajax requests, much easier for cross browser compatibility.
I am trying to using the JS to take user input and modify certain object attributes based on the user's input. I am storing the object's index in the select's alt attribute in order to use that to update the correct object. I'm getting an error: element[Payment_Format_name] is undefined
The WF.php file takes data from a CSV and formats it into a mulch-dimensional object.
$(document).ready(function() {
$.getJSON('WF.php', function(data) {
var newDiv, NewDiv2, NewDiv3,InvoiceInfo, count, DeliveryMethod, PaymentFormat, Payment_Format_id, Payment_Format_name;
count = 0;
$.each(data, function(index, element) {
count = count + 1;
//document.write (count);
newDiv = $('<div/>').addClass('row').appendTo('#showdata');
newDiv3 = $('<div/>').addClass('hd').appendTo(newDiv);
$('<div class="hd_field">' + element['PmtRec']['RcvrParty']['Name']['Name1'] + '</div>').appendTo(newDiv3);
if (element['PmtRec']['PmtMethod'] === 'CHK'){
$('<div class="hd_field">Delivery Method: <select alt="Delivery_Method" " id="Delivery' + count +'" class="Delivery_Method"><option value="100" selected="selected">US Mail</option><option value="300">Foreign Mail</option><option value="J00">Certified Mail with Return Receipt</option></select><div id="Selected_Method' + count +'"></div></div>').appendTo(newDiv3);
}
else if (element['PmtRec']['PmtMethod'] === 'DAC') {
$('<div class="hd_field">Payment Format: <select alt="'+index +'" id="Payment_' + count +'" class="Payment_Format"><option value="CTX" selected="selected">Company to Company</option><option value="PPD">Company to Person</option></select><div id="Selected_Format'+count+'"></div></div>').appendTo(newDiv3);
}
$('<div class="hd_field">' + 'Total: ' + element['PmtRec']['CurAmt'] + '</div>').appendTo(newDiv3);
InvoiceInfo = element['PmtRec']['PmtDetail']['InvoiceInfo'];
$.each(InvoiceInfo, function(index, element) {
newDiv2 = $('<div/>').addClass('sub_row').appendTo(newDiv);
$('<div class="field">' + element['InvoiceNum'] + '</div>').appendTo(newDiv2);
$('<div class="field">' + element['NetCurAmt'] + '</div>').appendTo(newDiv2);
});
$('select.Payment_Format').change(function(){
Payment_Format_id = ($(this).attr('id').match(/[\d]+$/));
Payment_Format_name = ($(this).attr('alt'));
//alert(Payment_Format_name);
PaymentFormat = ($(this).val());
element[Payment_Format_name] = Payment_Format_name;
element[Payment_Format_name]['PmtRec']['PmtFormat'] = PaymentFormat;
$('#Selected_Format' + Payment_Format_id).text('Selected Format: ' + element[Payment_Format] );
});
});
console.log(data);
});
});
PHP (this is a snippet, I'm actually creating a lot more elements here)
if (($handle = fopen('upload/BEN-new.csv', "r")) === FALSE) {
die('Error opening file');
}
$headers = fgetcsv($handle, 1024, ',');
$cardCodes = array();
$payments = array();
$details = array ();
while ($row = fgetcsv($handle, 1024, ",")) {
$cardCodes[] = array_combine($headers, $row);
}
$prevCode = '';
foreach ($cardCodes as $key => $value) {
$payments[$value['CardCode']]['PmtRec']['PmtCrDr'] = 'C';
$payments[$value['CardCode']]['PmtRec']['PmtFormat'] = 'CTX';
fclose($handle);
echo json_encode($payments)
Ok, so for starters,
$('select.Payment_Format').change(function(){
Payment_Format_id = ($(this).attr('id').match(/[\d]+$/));
Payment_Format_name = ($(this).attr('alt'));
PaymentFormat = ($(this).val());
element[Payment_Format_name] = Payment_Format_name;
element[Payment_Format_name]['PmtRec']['PmtFormat'] = PaymentFormat;
$('#Selected_Format' + Payment_Format_id).text('Selected Format: ' + element[Payment_Format] );
});
});
is not what you want - this function is reassigned to the change event of the 'select.Payment_Fomat' element for each iteration of $.each(data, function(index, element). The event listener should be added outside the $.each function, inside the $.getJson call and it needs to loop over the elements object, and try to find the correct data to update.
Apologies for the uselessness earlier, it was 5am and apparently I was slightly delusional.