mxCodec doesn't decode xml correctly - reactjs

I integrated mxGraph(mxgraph npm package) in my react app, so when I trying to load graph using xml, I am getting an error in console
TypeError: geo.clone is not a function
The same I am doing in single html file and it's working.
I investigated and found that the mxCell in react app is different from the html one.
In case of HTML there is filled geometry prop instead of react(check screens below)
Сan someone help me to decode xml correctly?
Decoded mxCell from single HTML console: https://monosnap.com/file/yAHAi29zFGFpauqU2RtDcvmfPpZ0YJ
Decoded mxCell from React app console: https://monosnap.com/file/0XxPwyEracX7hMCnMHckAmI8Rl6OEh
Source code from React component:
const graph = new mx.mxGraph(this.automationRef.current)
new mx.mxRubberband(graph);
const xml = '<root>...</root>';
const doc = mx.mxUtils.parseXml(xml);
const codec = new mxCodec(doc);
let elt = doc.documentElement.firstChild;
const cells = [];
while (elt != null){
const cell = codec.decodeCell(elt)
cells.push(cell);
graph.refresh();
elt = elt.nextSibling;
}
graph.addCells(cells);

Found the issue.
Here's the solution:
https://github.com/jgraph/mxgraph/issues/301#issuecomment-514284868
Quote:
you should add
window['mxGraphModel'] = mxGraphModel;
window['mxGeometry'] = mxGeometry;
before
let doc = mxUtils.parseXml(xml);
let codec = new mxCodec(doc);
codec.decode(doc.documentElement, graph.getModel());'
I found that the decode method resolve xml need windows param
End quote

Related

Read excel that is in the src folder of React app

I have creates a react app using react CLI.
I have now created a folder called data now I want to read that data using the xlsx npm package. However, it is not working. I think it may have something to do with the way I may be referring to the excel file because I get a warning as "Property 'Sheets' does not exist on type 'string'" (Pic below)
I thought it would be easy to read an excel (that too a local one), but I am not able to figure it out. Can anyone help? I looked at a lot of SO questions related to this but no success.
My Code
import "./App.css";
import XLSX from "xlsx";
let fileName = "./data/menu.xlsx";
var first_worksheet = fileName.Sheets[fileName.SheetNames[0]];
var data = XLSX.utils.sheet_to_json(first_worksheet, { header: 1 });
console.log(fileName);
Your fileName is just a string with your path right now. You're not actually parsing it as an Excel sheet yet, so the property Sheets will not exist on it.
You need to actually read the file from the filesystem, and then use XLSX to parse it into a format you can use to programmatically interact with it. Since you're using react, you can look at the react examples in the XLSX repo for an idea of how to go about it. The included demos only cover react-native apps, however, so you may also want to start looking into ways to retrieve and parse files on the local filesystem from the browser, like FileReader and fetch. Then, once you have the file loaded into memory, you can call XLSX.read(file) to fully interpret it as an Excel worksheet.
I found the answer to my question in here Excel to JSON javascript code?
The answer that was useful for me was the answer from user7456320 (the code is copied below as well).
All that was needed was the XLSX library. I used the code below with useEffect hook in my react component to run once when the page loads.
<!doctype html>
<html>
<head>
<title>Excel to JSON Demo</title>
<script src="xlsx.full.min.js"></script>
</head>
<body>
<script>
/* set up XMLHttpRequest */
var url = "http://myclassbook.org/wp-content/uploads/2017/12/Test.xlsx";
var oReq = new XMLHttpRequest();
oReq.open("GET", url, true);
oReq.responseType = "arraybuffer";
oReq.onload = function(e) {
var arraybuffer = oReq.response;
/* convert data to binary string */
var data = new Uint8Array(arraybuffer);
var arr = new Array();
for (var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
var bstr = arr.join("");
/* Call XLSX */
var workbook = XLSX.read(bstr, {
type: "binary"
});
/* DO SOMETHING WITH workbook HERE */
var first_sheet_name = workbook.SheetNames[0];
/* Get worksheet */
var worksheet = workbook.Sheets[first_sheet_name];
console.log(XLSX.utils.sheet_to_json(worksheet, {
raw: true
}));
}
oReq.send();
</script>
</body>
</html>

React Native fetch wait for dynamic content

I have a React Native app that uses the dom-parser module to extract relevant pieces of information from a website, which is not owned by me. The information that I need is loaded dynamically in the page after it finishes loading in the browser. Is there a way to get this in a react native app using fetch()? I don't want the users to see the website open up in the app.
What I've tried:
const html = (await (await fetch(this.search_url)).text()); //get the document
var dom = parser.parseFromString(html); //parse it
var json = dom.getElementsByTagName("script")[5].innerHTML //this is the element that I need
console.log(json)
fetch(this.search_url).then((response)=>response.json()).then((json)=>{
var dom = parser.parseFromString(html);
var json = dom.getElementsByTagName("script")[5].innerHTML
console.log(json)
})
Both of these return a blank response as output. However, when I looked up the source of this.search_url in a browser, it is loading the data after a few seconds of loading the page. Is there a way to get this data in the app? Maybe some trick to make fetch() wait for a few seconds before writing the response?

Reat native - How to fetch the CSV data from a link?

The below Java code will extract the historical stock data from yahoo finance, but the output file is a CSV file that is being read and printed on the screen line by line.
But I want to do the same thing in React native.
It would be helpful if you guys can help me with the code for the same in react native.
String link="https://query1.finance.yahoo.com/v7/finance/download/TSLA?period1=1563992913&period2=1595615313&interval=1d&events=history";
URL url = new URL(link);
URLConnection urlConn = url.openConnection();
InputStreamReader inStream = new InputStreamReader(urlConn.getInputStream());
BufferedReader buf = new BufferedReader(inStream);
String line =buf.readLine();
while(line != null) {
System.out.println(line);
line=buf.readLine();
}
This is the data inside the link :
Date,Open,High,Low,Close,Adj Close,Volume
2019-07-24,259.170013,266.070007,258.160004,264.880005,264.880005,11072800
2019-07-25,233.500000,234.500000,225.550003,228.820007,228.820007,22418300
2019-07-26,226.919998,230.259995,222.250000,228.039993,228.039993,10027700
2019-07-29,227.089996,235.940002,226.029999,235.770004,235.770004,9273300
You could use a library such as Papa parse to do exactly this. It will also parse the data for you.
If we take the example from here, you could do something like this (assuming you would also like to print the data to the console):
import Papa from "papaparse"
const link = "https://query1.finance.yahoo.com/v7/finance/download/TSLA?period1=1563992913&period2=1595615313&interval=1d&events=history"
Papa.parse(link, {
download: true,
complete: results => console.log(results),
})

Page-layout -> getPrintArea() in office-JS is returning blank Object

we are working on developing excel add-in using office-JS and We are using "https://appsforoffice.microsoft.com/lib/1/hosted/office.js" official production API's.
we are able to set the "setPrintArea" to the given range through the API, But when we are trying to get the added print-area using getPrintArea() of pageLayout it is always returning blank JSON object "{}", as per documentation expectation is Object of RangeAreas.
My sample code is as follows -
const sheet = context.workbook.worksheets.getActiveWorksheet();
sheet.pageLayout.setPrintArea("B4:D30");
sheet.load("pageLayout");
await context.sync();
console.log(sheet.getPrintArea());
OUTPUT: Object {}
Can anyone please help and let us know what we are missing here?
When you call a get* method, it creates a whole new proxy object, which you then have to load and sync before you can read it. So the call to getPrintRange has to come before the load and sync. The following code works:
await Excel.run(async (context) => {
const sheet = context.workbook.worksheets.getActiveWorksheet();
sheet.pageLayout.setPrintArea("B4:D30");
let printArea = sheet.pageLayout.getPrintArea();
printArea.load("address");
await context.sync();
console.log(printArea);
console.log(printArea.address);
});

How to send parsed .csv file as a byte array or ArrayBuffer data from Node.js backend to AngularJS frontend?

I'm working on AngularJS app.
Module I'm currently working on should be able to either show a preview of a spreadsheet file or allow to download it.
The steps:
When clicked on "Preview File" it should send request with needed file's name as a parameter of POST request.
Backend will find neede file, which is a .csv file, convert it to byte array type and send it to frontend.
Frontend should handle this byte array and convert it to .xls or .xlsx filetype
The spreadsheet data should be opened in some small preview read-only window, like 1000x1000 px.
The POST request line looks like that:
this.$http.post(this.url + 'endpoint/getFile', params,
{responseType: "arraybuffer", showLoadingOverlay: true}
)
The response looks indeed like ArrayBuffer: three of it in one object, i.e. Uint8Array, Uint16Array and Uint32Array.
The code which should read this and convert to content suitable for preview is not working:
const byteArray = new Uint8Array(data);
const blob = new Blob([byteArray], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const objectUrl = URL.createObjectURL(blob);
this.$window.open(objectUrl, 'C-Sharpcorner', 'width=1000,height=1000');
Because when created the blob, it already has 0 length in bytes, so there's no data inside.
The matter of visualising the .xls in browser window, I think, can be achieved with canvas-datagrid library. Haven't used but it looks cool.
Also, I have a problem with trying to set up a mock data for node.js (and AngularMock), for local testing when there's no data on a java backend.
I'm using 'fs' and 'csv-parse':
const fs = require('fs');
const csvParse = require("csv-parse/lib/es5");
module.exports = function stir(app) {
const getFile = () => {
const csvOutput = csvParse('../static/someData.csv', (parsed) => {
return parsed;
});
fs.readFileSync(csvOutput);
};
app.post('/stir/getFile', (req, res) => res.json(getFile()));
};
Which results in error:
TypeError: path must be a string or Buffer
What is the proper way of parsing the .csv using 'csv-parse' and sending parsed data as an ArrayBuffer to frontend in Node and AngularMock?
csv-parse docs are telling that underneath, the lib will convert the parsed object to node stream.
So why that error happens?

Resources