Can't create xlsx files with Firebase Cloud Functions - node.js

I followed the basic usage tutorial for excel4node package.
For running the code, I have an https function which will create an Excel.xlsx file in the same directory as index.js on my local system.
The problem, however, is that every time I call the function, a zero byte Excel.xls file is created.
The function body is this:
const createXlxsFile = (req, res) => {
const xl = require('excel4node');
// Create a new instance of a Workbook class
const workbook = new xl.Workbook();
// Add Worksheets to the workbook
const worksheet = workbook.addWorksheet('Sheet 1');
const worksheet2 = workbook.addWorksheet('Sheet 2');
// Create a reusable style
const style = workbook.createStyle({
font: {
color: '#FF0800',
size: 12
},
numberFormat: '$#,##0.00; ($#,##0.00); -'
});
// Set value of cell A1 to 100 as a number type styled with paramaters of style
worksheet.cell(1, 1).number(100).style(style);
// Set value of cell B1 to 300 as a number type styled with paramaters of style
worksheet.cell(1, 2).number(200).style(style);
// Set value of cell C1 to a formula styled with paramaters of style
worksheet.cell(1, 3).formula('A1 + B1').style(style);
// Set value of cell A2 to 'string' styled with paramaters of style
worksheet.cell(2, 1).string('string').style(style);
// Set value of cell A3 to true as a boolean type styled with paramaters of style but with an adjustment to the font size.
worksheet.cell(3, 1).bool(true).style(style).style({ font: { size: 14 } });
workbook.write('Excel.xlsx');
res.end('DOC CREATED');
};
This code is working fine with standard Node.js, but not with Firebase cloud functions. Is there a restriction with writing files with the functions?
I'm having the same issue even when using the Xlsx-populate package.

OK. Figured out the issue.
The thing is that the cloud function don't allow you to write to any directory in the OS.
The only place where you have the write access to is the /tmp in the cloud functions.
On your local PC, however, this too will crash (tested in Windows 10). Probably because I had not created the C:/tmp folder.
To fix this, you can use the tmpdir() method of the os module in Node.js
const os = require('os');
const path = require('path');
const pathToSave = path.join(os.tmpdir(), 'Excel.xlsx');
While deploying the code, you will need to replace the os.tmpdir() with `/tmp'.
const pathToSave = path.join('/tmp', 'Excel.xlsx');
I hope this helps.

workbook.write('Excel.xlsx'); is asynchronous. The docs says it takes a callback which is invoked after completion. Use that to terminate the function. Right now, you're terminating early before the write can finish.
wb.write();
The write() method can accept a single filename, a
filename with callback function or an HTTP response object.
wb.write('ExcelFile.xlsx', function (err, stats) {
if (err) {
res.send(500);
} else {
res.end('DOC CREATED');
}
});
It looks like this may work as well:
wb.write('ExcelFile.xlsx', res);

Related

How to get a mapped Url in Vite? Source map

I have not yet entered the world of plugins, but I have one idea and I want to test it as simple as possible.
Question:
I have a url WITHOUT SOURCE MAP, e.g. instance/$$self.$$.update#http://localhost:5173/src/lib/ContextListItem.svelte:448:15.
And I want to get from it a URL WITH SOURCE MAP, e.g. http://localhost:5173/src/lib/ContextListItem.svelte:19:11.
Theoretically it is a simple function:
const mappedUrl = getMappedUrl(url)
How to get it in Vite?
What do I need it for?
I have such code:
window._log = console.log.bind(console);
console.log = function (...a) {
try {
throw Error("aa");
} catch (err) {
const fileUrl = err.stack.split("\n")[1].split("#")[1].replace(`${location.origin}/`,"").split(":")[0];
window._log(...a, `${location.origin}/__open-in-editor?file=${/* encodeURIComponent */(fileUrl)}`);
}
}
And I want (as you can see) to add a link to the location in the code (thanks to the method from __open-in-editor).
Here I am missing a specific line and column in the file.
In Microsoft Egde any link from the console can direct to VSCode, but unfortunately in other browsers this is not there (e.g. my bug for Firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1771862).
This is the answer, But it only works asynchronously, so it's not suitable for replacing console.log. :/
Use on the Web - https://github.com/mozilla/source-map/#use-on-the-web
Consuming a source map - https://github.com/mozilla/source-map/#consuming-a-source-map
<script src="https://unpkg.com/source-map#0.7.3/dist/source-map.js"></script>
<script>
sourceMap.SourceMapConsumer.initialize({
"lib/mappings.wasm": "https://unpkg.com/source-map#0.7.3/lib/mappings.wasm"
});
</script>
<script type="module">
export async function aaa (origin, fileUrl, line, column) {
const res = await fetch(`${origin}/${fileUrl}.map`);
const json = await res.json();
const place = await sourceMap.SourceMapConsumer.with(json, null, consumer => {
const place = consumer.originalPositionFor({
line: Number(line),
column: Number(column)
});
return place;
});
return place;
}
</script>

Write data in text file using node

I am new to node and file handling. below my code work perfectly
const data = 'Dummy data';
fs.appendFile('./../log/TempLog.txt', data, function(error){
});
But when same code place inside the function which is in other module file is not written i tried it in many ways please check my code below
const fs = require("fs");
function WriteData(data) {
fs.appendFile('./../log/TempLog.txt', data, function(error){
});
}
module.exports.WriteData = WriteData;
Also the Writedata function called form index module as shown below
const writeLog = require('./public/writeLog');
server.on("connection", function (socket) {
const decoder = new StringDecoder('utf8');
socket.on("data", function (d) {
writeLog.WriteData(decoder.write(d));
});
}
am i doing it wrong? Thanks in advance
after reviewing my own code i finally got the solution below :
The problem was with my path although the writedata.js module is in public folder but this will loaded into index.js as i imported into main module so i give path of text file referring to index file.

returning result from another nodejs file

i am working on a project in which a nodejs program calls another program in a separate file.
this is how i've added the two:
var ocr = require('./index.js'); //this imports the file
var arr = ocr.ocr_pan(); //this calls the function in that file
am not sure but I guess the problem is that the process resumes before ocr.ocr_pan() returns the result and var arr becomes undefined.
or there is some problem in returning the result from ocr.ocr_pan()
I simply use return.
and I have also tried this : How to return array from module in NodeJS
didn't work
what more can be done?
Assuming that this file is the same directory as index.js file, code in index.js should be something like this:
// Write your function
var ocr_pan = function() {
// Do whatever you like
return result;
};
// Export it, make publicly visible to other files
module.exports = {
ocr_pan: ocr_pan
};

PDF to Text extractor in nodejs without OS dependencies

Is there a way to extract text from PDFs in nodejs without any OS dependencies (like pdf2text, or xpdf on windows)? I wasn't able to find any 'native' pdf packages in nodejs. They always are a wrapper/util on top of an existing OS command.
Thanks
Have you checked PDF2Json? It is built on top of PDF.js. Though it is not providing the text output as a single line but I believe you may just reconstruct the final text based on the generated Json output:
'Texts': an array of text blocks with position, actual text and styling informations:
'x' and 'y': relative coordinates for positioning
'clr': a color index in color dictionary, same 'clr' field as in 'Fill' object. If a color can be found in color dictionary, 'oc' field will be added to the field as 'original color" value.
'A': text alignment, including:
left
center
right
'R': an array of text run, each text run object has two main fields:
'T': actual text
'S': style index from style dictionary. More info about 'Style Dictionary' can be found at 'Dictionary Reference' section
After some work, I finally got a reliable function for reading text from PDF using https://github.com/mozilla/pdfjs-dist
To get this to work, first npm install on the command line:
npm i pdfjs-dist
Then create a file with this code (I named the file "pdfExport.js" in this example):
const pdfjsLib = require("pdfjs-dist");
async function GetTextFromPDF(path) {
let doc = await pdfjsLib.getDocument(path).promise;
let page1 = await doc.getPage(1);
let content = await page1.getTextContent();
let strings = content.items.map(function(item) {
return item.str;
});
return strings;
}
module.exports = { GetTextFromPDF }
Then it can simply be used in any other js file you have like so:
const pdfExport = require('./pdfExport');
pdfExport.GetTextFromPDF('./sample.pdf').then(data => console.log(data));
Thought I'd chime in here for anyone who came across this question in the future.
I had this problem and spent hours over literally all the PDF libraries on NPM. My requirements were that I needed to run it on AWS Lambda so could not depend on OS dependencies.
The code below is adapted from another stackoverflow answer (which I cannot currently find). The only difference being that we import the ES5 version which works with Node >= 12. If you just import pdfjs-dist there will be an error of "Readable Stream is not defined". Hope it helps!
import * as pdfjslib from 'pdfjs-dist/es5/build/pdf.js';
export default class Pdf {
public static async getPageText(pdf: any, pageNo: number) {
const page = await pdf.getPage(pageNo);
const tokenizedText = await page.getTextContent();
const pageText = tokenizedText.items.map((token: any) => token.str).join('');
return pageText;
}
public static async getPDFText(source: any): Promise<string> {
const pdf = await pdfjslib.getDocument(source).promise;
const maxPages = pdf.numPages;
const pageTextPromises = [];
for (let pageNo = 1; pageNo <= maxPages; pageNo += 1) {
pageTextPromises.push(Pdf.getPageText(pdf, pageNo));
}
const pageTexts = await Promise.all(pageTextPromises);
return pageTexts.join(' ');
}
}
Usage
const fileBuffer = fs.readFile('sample.pdf');
const pdfText = await Pdf.getPDFText(fileBuffer);
This solution worked for me using node 14.20.1 using "pdf-parse": "^1.1.1"
You can install it with:
yarn add pdf-parse
This is the main function which converts the PDF file to text.
const path = require('path');
const fs = require('fs');
const pdf = require('pdf-parse');
const assert = require('assert');
const extractText = async (pathStr) => {
assert (fs.existsSync(pathStr), `Path does not exist ${pathStr}`)
const pdfFile = path.resolve(pathStr)
const dataBuffer = fs.readFileSync(pdfFile);
const data = await pdf(dataBuffer)
return data.text
}
module.exports = {
extractText
}
Then you can use the function like this:
const { extractText } = require('../api/lighthouse/lib/pdfExtraction')
extractText('./data/CoreDeveloper-v5.1.4.pdf').then(t => console.log(t))
Instead of using the proposed PDF2Json you can also use PDF.js directly (https://github.com/mozilla/pdfjs-dist). This has the advantage that you are not depending on modesty who owns PDF2Json and that he updates the PDF.js base.

How ensure default data in NeDB?

I'm trying to use NeDB as storage for my data in node-webkit application. I have the single collection named config.db:
var Datastore = require('nedb')
, path = require('path')
, db = new Datastore({ filename: path.join(require('nw.gui').App.dataPath, 'config.db') });
When user opens node-webkit application first time my config.db should have default data like:
{
color: "red",
font: 'bold'
...
}
Does NeDB have option for providing default data if there are no yet? Or What it the best way to save it if config.db is empty (in case if user opens node-webkit application first time)?
As far as I know NeDB does not have an option to create initial data.
I think the easiest way to achieve this is to simply query whether there is data. If counting documents returns 0, obviously the initial data have not yet been saved, so you should do this now.
If you include this check in the startup code of your application, it will automatically initialize the data on first run, and afterwards simply do nothing.
I came across this question while looking for a similar solution. I thought I'd share what I ended up with (this is a module):
var fs = require("fs");
module.exports = function (app) {
var customizationService = app.service("customization");
fs.readFile("./db/customization", "utf8", function (err, data) {
if (err) {
return console.log(err);
}
if (data) {
// Sweet, carry on
} else {
var customOptions = {
SiteTitle: "VendoMarket",
SiteTagline: "The freshest eCommerce platform around"
};
// Save data to the locations service
customizationService.create(customOptions);
}
});
};
And then in my app.js file:
//--------------------------------------
// Initialize
//--------------------------------------
var vendoInit = require("./src/init");
vendoInit(app);
(My app.js file is at the base of my project, src is a folder next to it)

Resources