CREATE PDF FROM GOOGLE SHEETS - pdf

function createBulkPDFs(){
const docFile = DriveApp.getFileById("id");
const tempFolder = DriveApp.getFolderById("id");
const pdfFolder = DriveApp.getFolderById("id");
const currentSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1")
const data = currentSheet.getRange(2,1,currentSheet.getLastRow()-1,15).getDisplayValues();
let errors = [];
data.forEach(row => {
try{
createpdf(row[0],row[1],row[5],row[6],row[7],row[8],row[9],row[0] + " " + row[1],docFile,tempFolder,pdfFolder);
errors.push("");
} catch(err){
errors.push("Failed");
}
}); //close forEach
currentSheet.getRange(2,15,currentSheet.getLastRow()-1,1).setValues(errors);
}
function
createpdf(First_name,Last_name,Description,Address,Location,Date_of_letter,Date_of_Def,pdfname,docFile,tempFolder,pdfFolder) {
const tempFile = docFile.makeCopy(tempFolder);
const tempDocFile = DocumentApp.openById(tempFile.getId());
const body = tempDocFile.getBody();
body.replaceText("{First name}",First_name);
body.replaceText("{Last name}",Last_name);
body.replaceText("{Description}",Description);
body.replaceText("{Address}",Address);
body.replaceText("{Location}",Location);
body.replaceText("{Date of letter}",Date_of_letter);
body.replaceText("{Date of Def}",Date_of_Def);
tempDocFile.saveAndClose();
const pdfContentBlob = tempFile.getAs(MineType.Pdf);
pdfFolder.createFile(pdfContentBlob).setName("pdfname");

I tried to replicate your code and found some issues.
The use of setValues() when populating rows of data. The data should be in 2 dimensional. Each sub-array represents row of data.
The value used in getAs() should be application/pdf instead of MineType.pdf.
Here is my sample data:
Code:
function createBulkPDFs() {
const docFile = DriveApp.getFileById("id");
const tempFolder = DriveApp.getFolderById("id");
const pdfFolder = DriveApp.getFolderById("id");
const currentSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1")
const data = currentSheet.getRange(1, 1, currentSheet.getLastRow(), 11).getDisplayValues();
let errors = [];
data.forEach(row => {
try {
createpdf(row[0], row[1], row[5], row[6], row[7], row[8], row[9], row[0] + " " + row[1], docFile, tempFolder, pdfFolder);
errors.push("Success");
} catch (err) {
errors.push("Failed");
}
}); //close forEach
let newArr = [];
while(errors.length > 0) {
newArr.push(errors.splice(0,1));
}
currentSheet.getRange(1, 12, currentSheet.getLastRow(), 1).setValues(newArr);
}
function createpdf(First_name, Last_name, Description, Address, Location, Date_of_letter, Date_of_Def, pdfname, docFile, tempFolder, pdfFolder){
const tempFile = docFile.makeCopy(tempFolder);
const tempDocFile = DocumentApp.openById(tempFile.getId());
const body = tempDocFile.getBody();
body.replaceText("{First name}", First_name);
body.replaceText("{Last name}", Last_name);
body.replaceText("{Description}", Description);
body.replaceText("{Address}", Address);
body.replaceText("{Location}", Location);
body.replaceText("{Date of letter}", Date_of_letter);
body.replaceText("{Date of Def}", Date_of_Def);
tempDocFile.saveAndClose();
const pdfContentBlob = tempFile.getAs('application/pdf');
pdfFolder.createFile(pdfContentBlob).setName(pdfname);
}
PDF:
Sheets:
References:
getAs()
setValues()

Related

ethers.js, Swap on uniswapV3 failed tx

Im trying to use exactInput() function for UniV3 interface but when trying to execute the code the transactions fails https://goerli.etherscan.io/tx/0xb0d5e4b491610b9db8d98cc938008ba2a4e1a06e67b05ed87ac6c0ca3ad61dab
I know eth send shows 0 in this one but even especifying amount it fails, I dont know what to change..
I have checked many codes out there and cant see the mistake, please could someone give me some advice?
const {abi: V3SwapRouterABI} = require('#uniswap/v3-periphery/artifacts/contracts/interfaces/ISwapRouter.sol/ISwapRouter.json')
const { ethers } = require("ethers")
require("dotenv").config()
const INFURA_URL_TESTNET = process.env.INFURA_URL_TESTNET
const PRIVATE_KEY = process.env.PRIVATE_KEY
const WALLET_ADDRESS = process.env.WALLET_ADDRESS
// now you can call sendTransaction
const wethToken= "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6"
const Uni= "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"
const UniswapRouter="0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
const UniV3Contract = new ethers.Contract(
UniswapRouter,
V3SwapRouterABI
)
const provider = new ethers.providers.JsonRpcProvider(INFURA_URL_TESTNET)
const wallet = new ethers.Wallet(PRIVATE_KEY)
const signer = wallet.connect(provider)
const FEE_SIZE = 3
function encodePath(path, fees) {
if (path.length != fees.length + 1) {
throw new Error('path/fee lengths do not match')
}
let encoded = '0x'
for (let i = 0; i < fees.length; i++) {
// 20 byte encoding of the address
encoded += path[i].slice(2)
// 3 byte encoding of the fee
encoded += fees[i].toString(16).padStart(2 * FEE_SIZE, '0')
}
// encode the final token
encoded += path[path.length - 1].slice(2)
return encoded.toLowerCase()
}
async function getToken() {
const path = encodePath([wethToken, Uni], [3000])
const deadline = Math.floor(Date.now()/1000) + (60*10)
const params = {
path: path,
recipient: WALLET_ADDRESS,
deadline: deadline,
amountIn: ethers.utils.parseEther('0.01'),
amountOutMinimum: 0
}
const encodedData = UniV3Contract.interface.encodeFunctionData("exactInput", [params])
const txArg = {
to: UniswapRouter,
from: WALLET_ADDRESS,
data: encodedData,
gasLimit: ethers.utils.hexlify(1000000)
}
const tx = await signer.sendTransaction(txArg)
console.log('tx: ', tx)
const receipt = tx.wait()
console.log('receipt: ', receipt)
}
module.exports = { getToken
You will need to remove the Deadline.. The new router 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45 moved deadline to the multi-call function (since the router is designed to be multi-call)

vscode extension API editor.replace replace only first match while match 2 instances

developing an VS code extension where
search for color hex code in whole css document
replace the color hex code with variable name
although it match all color hex code but replace the only first instance and stops
below is the code snippet
export function activate(context: vscode.ExtensionContext) {
let activeEditor = vscode.window.activeTextEditor;
function replaceWithinDocument() {
if (!activeEditor) {
return;
}
const text = activeEditor.document.getText();
const reg = new RegExp('(?<color>#[0-9a-f]{3,6})', 'gim');
const matches = text.matchAll(reg);
const variableList = {};
let i = 0;
for (const match of matches) {
const { index, groups } = match;
i++;
console.log({ match });
const startPos = activeEditor.document.positionAt(index!);
const endPos = activeEditor.document.positionAt(index! + match[0].length);
console.log({ i, startPos, endPos });
//Creating a new range with startLine, startCharacter & endLine, endCharacter.
let range = new vscode.Range(startPos, endPos);
// eslint-disable-next-line #typescript-eslint/naming-convention
Object.assign(variableList, { [`--var-${i}`]: groups?.color });
activeEditor.edit(editBuilder => {
editBuilder.replace(range, `--var-${i}`);
});
}
console.log({ variableList });
}
function triggerUpdateDecorations(throttle = false) {
if (timeout) {
clearTimeout(timeout);
timeout = undefined;
}
if (throttle) {
timeout = setTimeout(replaceWithinDocument, 500);
} else {
replaceWithinDocument();
}
}
if (activeEditor) {
triggerUpdateDecorations();
}
final document
body {
background-color: --var-1;
color: #223344;
}
you can see in the screenshot that console.log({ variableList }); have both color code in it
so what is wrong here?
See allow delay between edits via vscode extension api. Because of the particular nature of the editBuilder object
The editBuilder "expires" once you return from the callback passed to
TextEditor.edit.
you should put your matches loop inside the call to the edit call like this sample code:
// get your matches above first
editor.edit(editBuilder => {
let i = 0;
for (const match of matches) {
// build your replacement here
const matchStartPos = document.positionAt(match.index);
const matchEndPos = document.positionAt(match.index + match[0].length);
const matchRange = new Range(matchStartPos, matchEndPos);
editBuilder.replace(matchRange, resolvedReplace);
}
}).then(async (resolved) => {
});

Base64 String to pdf JavaScript React Native then download

I have a base64 string as follow:
I would like this base64 string ( or any base64 String) to be turned into a pdf, then downloaded in React Native. I am using expo for this. I have looked all over the place and could not find an answer.
If you just want to show the pdf in react-native.The react-native-pdf package can do the job.Use a source obj like this.
const source = {uri:"data:application/pdf;base64,JVBERi0xLjcKJc..."};
If you want to download base64 to pdf file, it's also simple.
var RNFetchBlob = require('react-native-fetch-blob').default;
const DocumentDir = RNFetchBlob.fs.dirs.DocumentDir;
let pdfLocation = DocumentDir + '/' + 'test.pdf';
RNFetchBlob.fs.writeFile(pdfLocation, pdf_base64Str, 'base64');
export async function downloadFile(url){
let binary = await getPdfBinary(url);
const base64Str = base64_encode(binary);
const DocumentDir = RNFetchBlob.fs.dirs.DocumentDir;
let pdfLocation = DocumentDir + '/' + 'test.pdf';
RNFetchBlob.fs.writeFile(pdfLocation, base64Str, 'base64');
}
I'm sorry I didn't notice that you are using expo. As I have never written codes about the file system part in the expo. After a lot try, it finally works. But only for android. I think you may hope the pdf file should be saved to an external storage path so the user can see it in the file app. But for ios, It is hard to reach that. A possible way is to use the share dialog. If you just want to save the pdf file to the document folder in the app(not see by the user), FileSystem.writeAsStringAsync is enough!Hope this is helpful!
import * as FileSystem from 'expo-file-system';
import { Platform } from 'react-native';
async function getPdfBinary(url) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "arraybuffer"; // get the binary
xhr.setRequestHeader('content-type', 'application/json');
xhr.onload = function (event) {
var arrayBuffer = xhr.response;
var byteArray = new Uint8Array(arrayBuffer);
var len = byteArray.byteLength;
var binary = ""
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(byteArray[i]);
}
resolve(binary);
}
xhr.send();
})
}
function base64_encode(str) {
var c1, c2, c3;
var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var i = 0,
len = str.length,
string = '';
while (i < len) {
c1 = str.charCodeAt(i++) & 0xff;
if (i == len) {
string += base64EncodeChars.charAt(c1 >> 2);
string += base64EncodeChars.charAt((c1 & 0x3) << 4);
string += "==";
break;
}
c2 = str.charCodeAt(i++);
if (i == len) {
string += base64EncodeChars.charAt(c1 >> 2);
string += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
string += base64EncodeChars.charAt((c2 & 0xF) << 2);
string += "=";
break;
}
c3 = str.charCodeAt(i++);
string += base64EncodeChars.charAt(c1 >> 2);
string += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
string += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
string += base64EncodeChars.charAt(c3 & 0x3F)
}
return string
}
const downloadForAos = async (pdfBase64Str) => {
const folder = FileSystem.StorageAccessFramework.getUriForDirectoryInRoot("test");
const permissions = await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync(folder);
if (!permissions.granted) return;
let filePath = await FileSystem.StorageAccessFramework.createFileAsync(permissions.directoryUri, "test.pdf", "application/pdf");
// let filePath = "content://com.android.externalstorage.documents/tree/primary%3Atest/document/primary%3Atest%2Ftest.txt";
console.log(pdfBase64Str, "====");
try {
await FileSystem.StorageAccessFramework.writeAsStringAsync(filePath, pdfBase64Str, { encoding: FileSystem.EncodingType.Base64 });
alert("download success!")
} catch (err) {
console.log(err);
}
}
const downloadForIos = async () => {
alert("try do it by yourself")
}
export async function downloadPdf(url) {
let binary = await getPdfBinary(url);
console.log(binary, "=====")
const base64Str = base64_encode(binary);
if (Platform.OS === "ios") {
downloadForIos(base64Str);
} else {
downloadForAos(base64Str);
}
}

How to write unit test component with FileReader.addEventListener in angular 8?

I use angular 8 and i want to test my component with FileReader.
I can not test a FileReader in my processFile function.
Maybe my work is badly written? Can you help me please to understand.
IF I understand correctly, I have to test a class (Filereader) in a process function
my component
processFile(imageInput: any) {
const file: File = imageInput.files[0];
const reader = new FileReader();
let size: number = 2097152
if (file) {
if (file.size <= size) {
this.sharingDataService.setUploadIsOk(true)
reader.addEventListener('progress', (event:any) =>{
this.progressValue = this.progressBar(event)
if (event.lengthComputable) {
// console.log(event.loaded+ " / " + event.total)
}
})
reader.addEventListener('loadstart', (event:any) =>{
this.progressValue =0;
this.textDuringUploadBefore = "No"
this.textDuringUploadAfter = ''
// console.log('start');
})
reader.addEventListener('loadend', (event:any) =>{
// console.log('end');
})
reader.addEventListener('load', (event: any) => {
console.log(event);
this.selectedFile = new ImageSnippet(event.target.result, file);
this.fileName = this.selectedFile.file.name;
this.fileNameExt =this.fileName.split('.').pop();
this.displayAddPhoto = false;
this.selectedFile.status = 'ok';
this.getLoadCallBack(file)
// this.ng2ImgMax.resizeImage(file, 900,600).subscribe(
// result =>{
// // console.log('compress', );
// this.textDuringUploadAfter= "Yes!!!"
// this.textDuringUploadBefore= ''
// this.fileForm.patchValue({
// image: new File([result], result.name)
// });
// this.imageIsLoad = true
// this.sharingDataService.setUploadIsOk(false)
// }
// )
// this.imageOutput.emit(this.fileForm)
});
reader.readAsDataURL(file);
} else {
const msg ="This picture is too big."
+ '<br/>' + "Please upload an image of less than 2MB."
// this.sharedFunctionService.openDialogAlert(msg, 'home')
this.errorService.openDialogError(msg)
this.imageIsLoad = false
this.sharingDataService.setUploadIsOk(false)
}
}
}
getLoadCallBack(file:File){
this.ng2ImgMax.resizeImage(file, 900,600).subscribe(
result =>{
// console.log('compress', );
this.textDuringUploadAfter= "Yes"
this.textDuringUploadBefore= ''
this.fileForm.patchValue({
image: new File([result], result.name)
});
console.log(this.fileForm);
this.imageIsLoad = true
this.sharingDataService.setUploadIsOk(false)
}
)
this.imageOutput.emit(this.fileForm)
}
my spec.ts
it('processFile', () => {
// const mockEvt = { target: { files: [fileInput] } };
// const mockReader: FileReader = jasmine.createSpyObj('FileReader', ['readAsDataURL', 'onload']);
// spyOn(window as any, 'FileReader').and.returnValue(mockReader);
// spyOn(component, 'getLoadCallBack').and.callThrough();
const file = new File([''], 'test-file.jpg', { lastModified: null, type: 'image/jpeg' });
const fileInput = { files: [file] };
const eventListener = jasmine.createSpy();
spyOn(window as any, "FileReader").and.returnValue({
addEventListener: eventListener
})
component.processFile(fileInput);
i have got an error
TypeError: reader.readAsDataURL is not a function
how to test my processFile function?
I trie many way but no sucess

csv files from S3 to Dynamodb with LAMBDA function

i have many csv files uploaded in the S3 and i want to send them to dynamodb (json format) how can i use lambda fuction to do it or is there any other solution
Just adding this solution that i have used.
First create you Lambda function, and give it the correct permission to your S3 Bucket and DynamoBD.
Lambda Function index.js
const doc = require('dynamodb-doc');
const dynamo = new doc.DynamoDB();
const AWS = require('aws-sdk');
const S3 = new AWS.S3({
maxRetries: 0,
region: 'SET_YOUR_REGION',
});
const insertSuccess = 0;
const insertErrors = 0;
function dynamoResultCallback(err, data) {
if (err) {
insertErrors++;
console.log("Insert Error: \n" + err);
//console.log(err, err.stack); // an error occurred
} else {
insertSuccess++;
}
}
//CONVERT TO JSON FUNCTION
function csvJSON(csv){
var lines=csv.split('\r');
for(var i = 0; i<lines.length; i++){
lines[i] = lines[i].replace(/\s/,'');//delete all blanks
}
var result = [];
var headers=lines[0].split(",");
for(var i=1;i<lines.length;i++){
var obj = {};
var currentline=lines[i].split(",");
for(var j=0;j<headers.length;j++){
//IF OBJECT KEY HAS NO VALUE,
//REMOVE IT OR DYNAMO DB WILL ERROR ON THAT OBJECT
if(currentline[j]!==''){
obj[headers[j].toString()] = currentline[j];
}
}
result.push(obj);
}
return result; //JavaScript object
// JSON.stringify(result); //JSON
}
exports.handler = (event, context, callback) => {
var srcBucket = event.Records[0].s3.bucket.name;
var srcKey = event.Records[0].s3.object.key;
S3.getObject({
Bucket: srcBucket,
Key: srcKey,
}, function(err, data) {
if (err !== null) {
return callback(err, null);
}
var fileData = data.Body.toString('utf-8');
var obj = csvJSON(fileData);
var string = JSON.stringify(obj);
console.log(string);
for (var i = 0; i < obj.length; i++) {
console.log('adding '+ JSON.stringify(obj[i]));
var params = {
Item: obj[i],
TableName: "YOUR_TABLE_NAME"
};
dynamo.putItem(params, dynamoResultCallback);
}
return callback(null, data);
});
};