I created a query that works on a single query but when I use ->get() it prompt
Object of class stdClass could not be converted to string
Here is my code:
$result = DB::table('users')->get(); // the data you want to download as csv
$csv = (array)$result; // stored the data in a array
return Excel::create('csvfile', function ($excel) use ($csv) {
$excel->sheet('mySheet', function ($sheet) use ($csv) {
$sheet->fromArray($csv);
});
})->download('xls');
Quick solution is decoding it
json_decode( json_encode($data), true);
Here is my code now
$data = DB::table('users')->get();
$csv= json_decode( json_encode($data), true);
return Excel::create('SalesReport', function($excel) use ($csv) {
$excel->sheet('Sales-Report', function($sheet) use ($csv)
{
$sheet->fromArray($csv);
});
})->download('xls');
Related
I am receiving a JSON object from the backend now I just want "result" array only in my template variable in my angular application from it.
{
"result":[
{"name":"Sunil Sahu",
"mobile":"1234567890",
"email":"abc#gmail.com",
"location":"Mumbai",
"Age":"19"
}
],
"status":200
}
Try with
variable_name["result"].
Try with
var data = response from the backend
var result = data.result;
$var = '{"result":[{"name":"Sunil Sahu","mobile":"1234567890","email":"abc#gmail.com","location":"Mumbai","Age":"19"}],"stats":200}';
If your $var is string, you need to turn it to "array" or "object" by json_decode() function
object:
$var_object = json_decode($var); //this will get an object
$result = $var_object->result; //$result is what you want to get
array:
$var_array = json_decode($var, true); //this will get an array
$result = $var_array['result']; //$result is what you want to get
Else if $var is object, direct use
$result = $var->result; //$result is what you want to get
As result is an array of objects, you can either use any loop to extract key value pair or you can directly access the array using index value.
var results = data["result"] // this would return an array
angular.forEach(results, function(value, key) {
//access key value pair
});
For accessing results in HTML, ng-repeat directive can be used.
Your question didn't explain further, but in the simple way try this :
const stringJson = `{
"result":[
{"name":"Sunil Sahu",
"mobile":"1234567890",
"email":"abc#gmail.com",
"location":"Mumbai",
"Age":"19"
}
],
"status":200
}`
const obJson = JSON.parse(stringJson);
console.log(obJson.result);
There is a problem with my work. since Firebase's Web/JavaScript API always returns the full tree under the nodes that we request.
So in my case i retrieved all of existing fields from firebase including sensitive fields first and after that I want to export to excel selected fields only, not all of the fields that i got. the problem is, I always succeed exported all existing fields, including the sensitive fields.
Can I export selected field only and exclude the sensitive field? Below is my code:
I retrieve all of my fields include the data from firebase in my .ts file like this:
getData() {
this.dataLoading = true;
this.querySubscription = this._backendService.getDocs('report')
.subscribe(members => {
this.members = members;
this.dataSource = new MatTableDataSource(members);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
},
(error) => {
this.error = true;
this.errorMessage = error.message;
this.dataLoading = false;
},
() => { this.error = false; this.dataLoading = false; });
}
//export func
exportAsXLSX():void{
this._backendService.exportAsExcelFile(this.members, 'sample');
}
My Backend service Code :
getDocs(coll:string,filters?:any){
this.itemsCollection=this.afs.collection<any>(this.getCollectionURL(coll));
return this.itemsCollection.valueChanges();
}
getCollectionURL(filter){
return "ReportApp/fajar/"+filter;
}
//export func
public exportAsExcelFile(json: any[], excelFileName: string): void {
const worksheet: XLSX.WorkSheet = XLSX.utils.json_to_sheet(json);
const workbook: XLSX.WorkBook = { Sheets: { 'data': worksheet }, SheetNames: ['data'] };
const excelBuffer: any = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
this.saveAsExcelFile(excelBuffer, excelFileName);
}
private saveAsExcelFile(buffer: any, fileName: string): void {
const data: Blob = new Blob([buffer], {type: EXCEL_TYPE});
FileSaver.saveAs(data, fileName + '_export_' + new Date().getTime() + EXCEL_EXTENSION);
}
as for reference im using code from here to exporting to excel :https://medium.com/#madhavmahesh/exporting-an-excel-file-in-angular-927756ac9857
as u can see I put all of my data into this.member variable and export em, But the result is that I exported all of em, i want to export selected fields only.
You will need to "trim down" the array of member data before you send it to your exportAsExcelFile() method. Your problem is that you are passing ALL of the member data to that export function. So the solution is to remove any sensitive information before you call the export function.
exportAsXLSX():void {
// TRIM DOWN ARRAY HERE
this._backendService.exportAsExcelFile(this.members, 'sample');
}
Since you didn't provide your member database structure, or details of what you consider sensitive information, I'll provide a generic example. You have an array of members... Most likely, you've made each "member" in the array into an object... so we need to loop over that array and delete the "sensitive" property of each member object.
As a precaution, since we don't want to delete the properties from the ACTUAL array, since arrays are reference-types, and since you might need those details elsewhere... let's make a copy of the array - a deep copy to ensure even nested objects are copied.
var newMemberArray = JSON.parse(JSON.stringify(this.members))
Then, we need to loop over that new array and delete our sensitive properties:
newMemberArray.forEach(function(m){
delete m.sensitivePropertyName1;
delete m.sensitivePropertyName2;
});
and pass that "sanitized" array to your export function... so putting all this together, something like:
exportAsXLSX():void {
var newMemberArray = JSON.parse(JSON.stringify(this.members))
newMemberArray.forEach(function(m){ delete m.sensitivePropertyName });
this._backendService.exportAsExcelFile(newMemberArray, 'sample');
}
*Disclaimer: untested code, for explanation purposes only
Take this object:
x = {
"key1": "xxx",
"key2": function(){return this.key1}
}
If I do this:
y = JSON.parse( JSON.stringify(x) );
Then y will return { "key1": "xxx" }. Is there anything one could do to transfer functions via stringify? Creating an object with attached functions is possible with the "ye goode olde eval()", but whats with packing it?
json-stringify-function is a similar post to this one.
A snippet discovered via that post may be useful to anyone stumbling across this answer. It works by making use of the replacer parameter in JSON.stringify and the reviver parameter in JSON.parse.
More specifically, when a value happens to be of type function, .toString() is called on it via the replacer. When it comes time to parse, eval() is performed via the reviver when a function is present in string form.
var JSONfn;
if (!JSONfn) {
JSONfn = {};
}
(function () {
JSONfn.stringify = function(obj) {
return JSON.stringify(obj,function(key, value){
return (typeof value === 'function' ) ? value.toString() : value;
});
}
JSONfn.parse = function(str) {
return JSON.parse(str,function(key, value){
if(typeof value != 'string') return value;
return ( value.substring(0,8) == 'function') ? eval('('+value+')') : value;
});
}
}());
Code Snippet taken from Vadim Kiryukhin's JSONfn.js or see documentation at Home Page
I've had a similar requirement lately. To be clear, the output looks like JSON but in fact is just javascript.
JSON.stringify works well in most cases, but "fails" with functions.
I got it working with a few tricks:
make use of replacer (2nd parameter of JSON.stringify())
use func.toString() to get the JS code for a function
remember which functions have been stringified and replace them directly in the result
And here's how it looks like:
// our source data
const source = {
"aaa": 123,
"bbb": function (c) {
// do something
return c + 1;
}
};
// keep a list of serialized functions
const functions = [];
// json replacer - returns a placeholder for functions
const jsonReplacer = function (key, val) {
if (typeof val === 'function') {
functions.push(val.toString());
return "{func_" + (functions.length - 1) + "}";
}
return val;
};
// regex replacer - replaces placeholders with functions
const funcReplacer = function (match, id) {
return functions[id];
};
const result = JSON
.stringify(source, jsonReplacer) // generate json with placeholders
.replace(/"\{func_(\d+)\}"/g, funcReplacer); // replace placeholders with functions
// show the result
document.body.innerText = result;
body { white-space: pre-wrap; font-family: monospace; }
Important: Be careful about the placeholder format - make sure it's not too generic. If you change it, also change the regex as applicable.
Technically this is not JSON, I can also hardly imagine why would you want to do this, but try the following hack:
x.key2 = x.key2.toString();
JSON.stringify(x) //"{"key1":"xxx","key2":"function (){return this.key1}"}"
Of course the first line can be automated by iterating recursively over the object. Reverse operation is harder - function is only a string, eval will work, but you have to guess whether a given key contains a stringified function code or not.
You can't pack functions since the data they close over is not visible to any serializer.
Even Mozilla's uneval cannot pack closures properly.
Your best bet, is to use a reviver and a replacer.
https://yuilibrary.com/yui/docs/json/json-freeze-thaw.html
The reviver function passed to JSON.parse is applied to all key:value pairs in the raw parsed object from the deepest keys to the highest level. In our case, this means that the name and discovered properties will be passed through the reviver, and then the object containing those keys will be passed through.
This is what I did https://gist.github.com/Lepozepo/3275d686bc56e4fb5d11d27ef330a8ed
function stringifyWithFunctions(object) {
return JSON.stringify(object, (key, val) => {
if (typeof val === 'function') {
return `(${val})`; // make it a string, surround it by parenthesis to ensure we can revive it as an anonymous function
}
return val;
});
};
function parseWithFunctions(obj) {
return JSON.parse(obj, (k, v) => {
if (typeof v === 'string' && v.indexOf('function') >= 0) {
return eval(v);
}
return v;
});
};
The naughty but effective way would be to simply:
Function.prototype.toJSON = function() { return this.toString(); }
Though your real problem (aside from modifying the prototype of Function) would be deserialization without the use of eval.
I have come up with this solution which will take care of conversion of functions (no eval). All you have to do is put this code before you use JSON methods. Usage is exactly the same but right now it takes only one param value to convert to a JSON string, so if you pass remaning replacer and space params, they will be ignored.
void function () {
window.JSON = Object.create(JSON)
JSON.stringify = function (obj) {
return JSON.__proto__.stringify(obj, function (key, value) {
if (typeof value === 'function') {
return value.toString()
}
return value
})
}
JSON.parse = function (obj) {
return JSON.__proto__.parse(obj, function (key, value) {
if (typeof value === 'string' && value.slice(0, 8) == 'function') {
return Function('return ' + value)()
}
return value
})
}
}()
// YOUR CODE GOES BELOW HERE
x = {
"key1": "xxx",
"key2": function(){return this.key1}
}
const y = JSON.parse(JSON.stringify(x))
console.log(y.key2())
It is entirely possible to create functions from string without eval()
var obj = {a:function(a,b){
return a+b;
}};
var serialized = JSON.stringify(obj, function(k,v){
//special treatment for function types
if(typeof v === "function")
return v.toString();//we save the function as string
return v;
});
/*output:
"{"a":"function (a,b){\n return a+b;\n }"}"
*/
now some magic to turn string into function with this function
var compileFunction = function(str){
//find parameters
var pstart = str.indexOf('('), pend = str.indexOf(')');
var params = str.substring(pstart+1, pend);
params = params.trim();
//find function body
var bstart = str.indexOf('{'), bend = str.lastIndexOf('}');
var str = str.substring(bstart+1, bend);
return Function(params, str);
}
now use JSON.parse with reviver
var revivedObj = JSON.parse(serialized, function(k,v){
// there is probably a better way to determ if a value is a function string
if(typeof v === "string" && v.indexOf("function") !== -1)
return compileFunction(v);
return v;
});
//output:
revivedObj.a
function anonymous(a,b
/**/) {
return a+b;
}
revivedObj.a(1,2)
3
To my knowledge, there are no serialization libraries that persist functions - in any language. Serialization is what one does to preserve data. Compilation is what one does to preserve functions.
It seems that people landing here are dealing with structures that would be valid JSON if not for the fact that they contain functions. So how do we handle stringifying these structures?
I ran into the problem while writing a script to modify RequireJS configurations. This is how I did it. First, there's a bit of code earlier that makes sure that the placeholder used internally (">>>F<<<") does not show up as a value in the RequireJS configuration. Very unlikely to happen but better safe than sorry. The input configuration is read as a JavaScript Object, which may contain arrays, atomic values, other Objects and functions. It would be straightforwardly stringifiable as JSON if functions were not present. This configuration is the config object in the code that follows:
// Holds functions we encounter.
var functions = [];
var placeholder = ">>>F<<<";
// This handler just records a function object in `functions` and returns the
// placeholder as the value to insert into the JSON structure.
function handler(key, value) {
if (value instanceof Function) {
functions.push(value);
return placeholder;
}
return value;
}
// We stringify, using our custom handler.
var pre = JSON.stringify(config, handler, 4);
// Then we replace the placeholders in order they were encountered, with
// the functions we've recorded.
var post = pre.replace(new RegExp('"' + placeholder + '"', 'g'),
functions.shift.bind(functions));
The post variable contains the final value. This code relies on the fact that the order in which handler is called is the same as the order of the various pieces of data in the final JSON. I've checked the ECMAScript 5th edition, which defines the stringification algorithm and cannot find a case where there would be an ordering problem. If this algorithm were to change in a future edition the fix would be to use unique placholders for function and use these to refer back to the functions which would be stored in an associative array mapping unique placeholders to functions.
I have some code that iterates over the rows and columns of an Excel sheet and replaces text with other text. This is done with a service that has the excel file and a dictionary as parameters like this.
$mappedTemplate = $this->get('app.entity.translate')->translate($phpExcelObject, $dictionary);
The service itself looks like this.
public function translate($template, $dictionary)
{
foreach ($template->getWorksheetIterator() as $worksheet) {
foreach ($worksheet->getRowIterator() as $row) {
$cellIterator = $row->getCellIterator();
$cellIterator->setIterateOnlyExistingCells(false); // Loop all cells, even if it is not set
foreach ($cellIterator as $cell) {
if (!is_null($cell)) {
if (!is_null($cell->getCalculatedValue())) {
if (array_key_exists((string)$cell->getCalculatedValue(), $dictionary)) {
$worksheet->setCellValue(
$cell->getCoordinate(),
$dictionary[$cell->getCalculatedValue()]
);
}
}
}
}
}
}
return $template;
}
After some debugging I found out that the text actually is replaced and that the service works like it should. The problem is that when I return the new PHPExcel file as a response to download, the excel is empty.
This is the code I use to return the file.
// create the writer
$writer = $this->get('phpexcel')->createWriter($mappedTemplate, 'Excel5');
// create the response
$response = $this->get('phpexcel')->createStreamedResponse($writer);
// adding headers
$dispositionHeader = $response->headers->makeDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
$file_name
);
$response->headers->set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
$response->headers->set('Pragma', 'public');
$response->headers->set('Cache-Control', 'maxage=1');
$response->headers->set('Content-Disposition', $dispositionHeader);
return $response;
What am I missing?
Your code is missing the calls to the writer.
You only create the writer, but never use it, at least not in your shared code examples:
$objWriter = new PHPExcel_Writer_Excel2007($objPHPExcel);
$response = $this->get('phpexcel')->createStreamedResponse($objWriter)
Another thing is the content type: Do you have the apache content types setup correctly?
$response->headers->set('Content-Type', 'application/vnd.ms-excel; charset=utf-8');
I'm trying to get PHPExcel (rather, the Laravel wrapper for it: https://github.com/Maatwebsite/Laravel-Excel ) to export my view. The query I'm running returns multiple rows as a multidimensional array (I'm using DB::select and binding that way because the query is a bit complex for Fluent)
The results look like this:
array(3) {
[0]=> object(stdClass)#224 (3) {
["name"]=> string(13) "Administrator"
["TotalRequest"]=> string(6) "100.00"
["TotalGiven"]=> string(6) "150.00" }
[1]=> object(stdClass)#226 (3) {
["name"]=> string(14) "Beta Alpha Psi"
["TotalRequest"]=> string(6) "363.00"
["TotalGiven"]=> string(6) "200.00" }
[2]=> object(stdClass)#227 (3) {
["name"]=> string(30) "Student Government Association"
["TotalRequest"]=> string(7) "1225.00"
["TotalGiven"]=> string(6) "620.00" }
}
The Laravel-Excel package only takes in a $data array(), so I'm confused how to convert my multi-dimensional array into my view. I can get it to work if I use the alternative
View::make(xxxx)->with('example', $example)
Am I overlooking how to pass $data as an array when I have objects involved in this?
It's not a multi-dimensional array but an array of objects. If you pass the array to your view using something like this:
View::make('xxxx')->with('example', $example)
Then in your view you may loop it using #foreach, like this:
#foreach($example as $item)
{{ $item->name }}
{{ $item->TotalRequest }}
{{ $item->TotalGiven }}
#endforeach
Because, the array contains multiple stdClass objects and the first object is (0):
{
["name"]=> string(13) "Administrator"
["TotalRequest"]=> string(6) "100.00"
["TotalGiven"]=> string(6) "150.00"
}
So, you may also retrieve the first object from the $example array using something like $example[0] and to retrieve the second object you may use $example[1] and so on.
Well I Would suggest you simply change the Fetch Mode to return an array directly using a method like the one below
public function getQueryResult($returnQueryAs = null)'
{
$tablename = 'YourAwesomeTable';
if($returnQueryAs == 'array')
{
DB::connection()->setFetchMode(PDO::FETCH_ASSOC);
}
return DB::table($tablename)->get();
}
then do something like this
public function exportAsExcel()
{
$filename = 'nameoffile';
$data = $this->getQueryResult($as = 'array');
Excel::create($filename, function($excel) use ($filename, $data) {
// Set the title
$excel->setTitle($filename);
// Chain the setters
$excel->setCreator('Damilola Ogunmoye');
$excel->sheet('SHEETNAME', function($sheet) use ($data) {
$sheet->fromArray($data);
});
})->download('xls');
}
This Would get an associative array as opposed to an stdClass object which you can pass directly.