Can't stream PDF file (.net core 2.0) - asp.net-core

For a few days I have no idea how to solve my problem.
I need return to user PDF document dynamically generated based on ID. I use for this NReco.PdfGenerator.LT. When I running a project directly from VS2017 everything works fine and the file is downloaded. But if I publish a project on an IIS server and then try clicking on the button, will open a page that does not exist (HTTP ERROR 404).
Button:
<a asp-controller="Dokumenty" asp-action="PobierzPotwierdzenieDokPdf" asp-route-DokID="#item.Dok_DokID" class="btn btn-warning btn-sm"><i class="glyphicon glyphicon-print" title="Drukuj PDF"></i></a>
Controller:
public async Task<FileResult> PobierzPotwierdzenieDokPdf(int DokID)
{
var dokument = _context.Dokumenty.FirstOrDefault(i => i.Dok_DokID == DokID);
var notatki = _context.DokumentyNotatki.Where(d => d.DokNot_DokID == DokID);
viewDokumentPotwierdzeniePdf viewDokumentPotwierdzeniePdf = new viewDokumentPotwierdzeniePdf()
{
Dokument = dokument,
DokumentNotatka = notatki
};
var htmlContent = await _viewRenderService.RenderToStringAsync("Dokumenty/DokumentPotwierdzeniePdf", viewDokumentPotwierdzeniePdf);
var htmlToPdf = new HtmlToPdfConverter
{
PageHeight = 210,
PageWidth = 148,
Margins = new PageMargins() { Bottom = 5, Left = 5, Right = 5, Top = 5 },
Orientation = PageOrientation.Landscape,
PageFooterHtml = "<div style='font-family: Verdana, Geneva, Tahoma, sans-serif; font-size: 10px; text-align: center; color: grey;'>Strona <span class='page'></span> z <span class='topage'></span> | Operator drukujący: " + HttpContext.Session.GetString("Ope_Nazwisko") + " | Data wydruku: " + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss") + " | <b>System ERP Polimer</b></div>"
};
htmlToPdf.License.SetLicenseKey("PDF_Generator_Bin_Examples_Pack_0000000000", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
htmlToPdf.PdfToolPath = #"C:\Program Files\wkhtmltopdf\bin\";
byte[] pdfBytes = htmlToPdf.GeneratePdf(htmlContent);
FileResult fileResult = new FileContentResult(pdfBytes, "application/pdf")
{
FileDownloadName = dokument.Dok_NrKancelaryjny.Replace("/", "_") + ".pdf"
};
dokument.Dok_Wydruk = 1;
_context.Entry(dokument).State = EntityState.Modified;
await _context.SaveChangesAsync();
return fileResult;
}
IIS is trying to open the url http://domainname.int/Dokumenty/PobierzPotwierdzenieDokPdf?DokID=77 where the number at the end is the ID. But that page does not physically exist.
Please help. What am I doing wrong?
P.S. sorry for my English :)

Related

Can you pretty print IHtmlContent?

If I have a IHtmlContent can I pretty print it?
Example:
var html = new HtmlString("<article><h2>Hello!</h2></article>");
I want it pretty printed with line breaks and indention into:
<article>
<h2>Hello!</h2>
</article>
I do not want:
<article><h2>Hello!</h2></article>
You could try to JavaScript to add the line breaks and indention into, then, use <pre> tag to render the html content. Please check the following sample:
Index.cshtml:
#{
var html ="<article><h2>Hello!</h2></article>";
}
<div id="printdiv">
#Html.Raw(html)
</div>
<div id="output">
</div>
<input type='button' id='btn' value='Print' onclick='printDiv();'>
#section Scripts{
<script>
function printDiv() {
var divToPrint = document.getElementById('printdiv');
//display the pretty html content in the web page.
document.getElementById("output").innerHTML = "<pre>" + process(divToPrint.innerHTML).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") + "</pre>";
//create a new window to print the div content.
var newWin = window.open('', 'Print-Window');
newWin.document.open();
newWin.document.write('<html><body onload="window.print()"><pre>' + process(divToPrint.innerHTML).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">") + '</pre></body></html>');
newWin.document.close();
setTimeout(function () { newWin.close(); }, 10);
}
function process(str) {
var div = document.createElement('div');
div.innerHTML = str.trim();
return format(div, 0).innerHTML;
}
function format(node, level) {
var indentBefore = new Array(level++ + 1).join(' '),
indentAfter = new Array(level - 1).join(' '),
textNode;
for (var i = 0; i < node.children.length; i++) {
textNode = document.createTextNode('\n' + indentBefore);
node.insertBefore(textNode, node.children[i]);
format(node.children[i], level);
if (node.lastElementChild == node.children[i]) {
textNode = document.createTextNode('\n' + indentAfter);
node.appendChild(textNode);
}
}
return node;
}
</script>
}
The result like this:
You can parse it XML with XDocument.Parse then use XmlWriter with its settings set to Indent to true. Worked for me on my HTML too.
var html = new HtmlString("<article><h2>Hello!</h2></article>");
using var writer = new StringWriter();
html.WriteTo(writer, HtmlEncoder.Default);
var htmlString = writer.ToString();
var settings = new XmlWriterSettings
{
OmitXmlDeclaration = true,
Encoding = Encoding.UTF8,
Indent = true,
};
var sb = new StringBuilder();
using (var writer = XmlWriter.Create(sb, settings))
{
XDocument.Parse(htmlString).Save(writer);
}
Console.WriteLine(sb.ToString());

How to break the line with vue-typer without breaking word

I'm working with vue-typer and it adjusts on screen according to the space. But, depending the size of the screen, the vue-typer breaks the word. I want to break just when we have backspace. The code is:
<vue-typer
class="text-h4 font-weight-bold"
text="Nós acreditamos que o futuro pode ser incrível. Quer criar
ele com a gente?" :repeat='0'
></vue-typer><br>
Here is the image of how is working now
I dont know if anyone is still dealing with this issue, I have written a quick fix to the issue. Its not perfect but does the job.
You will run the text through a Method that will auto add in the line breaks automatically.
<div
style="
font-size: 30pt;
margin: auto;
color: white;
max-width: 600px;
"
ref="theRef"
>
<vue-typer
v-if="startTypers"
:text="[
formatText(
'TextHere',
'theRef',
22
),
]"
:repeat="0"
:shuffle="false"
initial-action="typing"
:pre-type-delay="70"
:type-delay="70"
:pre-erase-delay="2000"
:erase-delay="100"
erase-style="backspace"
:erase-on-complete="false"
caret-animation="blink"
></vue-typer>
</div>
mounted() {
setTimeout(() => {
this.startTypers = true;
}, 150);
}
The reason for the startTypers is because they will run the formatText method before the div has been rendered. Meaning you won't be able to get the clientWidth of the parent div.
formatText(text, ref, textSize = 22) {
let maxChars = Math.floor(this.$refs[ref].clientWidth / textSize);
let words = text.split(" ");
let breaked = "";
let currentCount = 0;
words.forEach((word) => {
currentCount += word.length;
currentCount += 1;
if (currentCount >= maxChars) {
currentCount = word.length;
breaked = `${breaked}\n${word} `;
} else {
breaked = `${breaked}${word} `;
}
});
return breaked;
},
The Parameters for formatText are the Text that you want to have the line breaks added in, The name of the ref, and the size of the span(Chars) that is rendered (22 was the default for the font and font-size I used in my use case, yours will vary)
Hopefully this helps
In order to break the text into chunks, consider the following
data() {
text : 'Hello World! I`m clarification masterjam!',
},
computed : {
textComputed() {
let n = "\n"
let breaked = this.text.match(/.{1,25}/g);
breaked[0];
var pos = breaked[0].lastIndexOf(' ');
breaked[0] = breaked[0].substring(0,pos)+n+breaked[0].substring(pos+1);
return breaked.join('')
},
}

Object is not moving proper with mouse movement in mobile devices

I am trying to move an object with mouse using pressmove event on the object. In PC and Tablet it is working well. But, in the mobile devices it is not working well as those have different width and height.
You can view the following URL:-
http://quirktools.com/screenfly/#u=http://saurabhysecit.byethost15.com/scratchGame_Canvas.html&w=320&h=568&a=37&s=1
Direct URL is - http://saurabhysecit.byethost15.com/scratchGame_Canvas.html
It has been generated from Animate CC.
These are the code below.
JS Code -
(function (lib, img, cjs, ss, an) {
var p; // shortcut to reference prototypes
lib.ssMetadata = [];
function mc_symbol_clone() {
var clone = this._cloneProps(new this.constructor(this.mode, this.startPosition, this.loop));
clone.gotoAndStop(this.currentFrame);
clone.paused = this.paused;
clone.framerate = this.framerate;
return clone;
}
function getMCSymbolPrototype(symbol, nominalBounds, frameBounds) {
var prototype = cjs.extend(symbol, cjs.MovieClip);
prototype.clone = mc_symbol_clone;
prototype.nominalBounds = nominalBounds;
prototype.frameBounds = frameBounds;
return prototype;
}
(lib.coin = function(mode,startPosition,loop) {
this.initialize(mode,startPosition,loop,{});
// Layer 1
this.shape = new cjs.Shape();
this.shape.graphics.f().s("#AA8801").ss(1,2,1).p("AH5AAQAACrhhCBQgIAKgIAKQgQAUgTASQiKCLjAAKQgNAAgOAAQi5AAiKh2QgRgOgQgRQiUiTAAjTQAAjDCBiOIAAgBQAJgKAKgKQAUgUAVgSQB9hlCigIQAOgBAOAAQAaAAAZACQAHAAAHABQCoAUB8B9QATASAQAUQBtCEAECvQAAADAAACQAAAFAAADg");
this.shape.setTransform(-4.8,0.1);
this.shape_1 = new cjs.Shape();
this.shape_1.graphics.f("#D9AE01").s().p("AlbGiQgTgQgSgSQigieAAjiQAAjhCgifQAWgWAXgTQCRh2DCgBQAdABAbACQC+ARCLCMQAUATASAWQB6CTAADEQAADGh6CSQgSAVgUATQiUCWjQAKIgdAAQjHAAiUh+gAgqnnQijAIh8BmQgVARgUAUIgUAUIAAABQiBCOAADEQAADSCVCTQAQARARAOQCJB2C6AAIAbAAQDAgJCJiMQATgSAQgUIAQgUQBhiBAAiqIAAgJIAAgGQgEithtiFQgQgTgTgTQh7h9ipgTIAAgDQgYgCgaAAQgVAAgVACg");
this.shape_1.setTransform(-3.3,-1.7);
this.shape_2 = new cjs.Shape();
this.shape_2.graphics.f("#FFCC00").s().p("AlDGFQgQgOgQgQQiViUAAjSQAAjDCBiPIAAAAIAUgVQAUgUAUgRQB9hmCigIQAWgCAVAAQAZAAAZACIAAADIgNgCQgZgCgbAAIgcABIAcgBQAbAAAZACIANACQCoATB8B9QATATAQAUQBsCEAFCvIAAAFIAAAIQAACqhhCCIgQATQgQAUgTATQiKCLjAAJIgbABQi5AAiKh3g");
this.shape_2.setTransform(-4.8,0.1);
this.shape_3 = new cjs.Shape();
this.shape_3.graphics.f("#695400").s().p("Ah6I1IgBAAQjHgKiUiJQCUB+DIAAIAeAAQDOgKCUiWQAUgTASgWQB6iSAAjFQAAjEh6iTQgSgWgUgUQiKiLi+gRQgbgDgdAAQjCAAiSB3QCSiBDBgKIABAAIAfAAIAbAAIAAAAQDXAJCbCcIAaAbIACAEQCJCcAADUIAAACQgBDViICaIgCAEQgMANgOANQikCmjpAAIgfAAg");
this.shape_3.setTransform(9,-1.7);
this.timeline.addTween(cjs.Tween.get({}).to({state:[{t:this.shape_3},{t:this.shape_2},{t:this.shape_1},{t:this.shape}]}).wait(1));
}).prototype = getMCSymbolPrototype(lib.coin, new cjs.Rectangle(-57.8,-58.2,113.9,113.1), null);
// stage content:
(lib.scratchGame_Canvas = function(mode,startPosition,loop) {
if (loop == null) { loop = false; } this.initialize(mode,startPosition,loop,{});
// timeline functions:
this.frame_0 = function() {
var pressBool=false;
var mask_mc = new createjs.Shape();
var bg_mc = new createjs.Bitmap("images/YLogo1.jpg");
//var coin_mc = new lib.coin();
var coin_mc = new createjs.Shape(new createjs.Graphics().beginFill("#FFFFFF").drawCircle(0, 0, 50));
coin_mc.x = stage.canvas.width/2;
coin_mc.y = stage.canvas.width/2;
stage.addChild(bg_mc, coin_mc);
createjs.Touch.enable(stage, false, true);
if(sRatio<1){
coin_mc.scaleX = coin_mc.scaleY = sRatio;
}
coin_mc.addEventListener('pressmove', moveCoin.bind(this));
coin_mc.addEventListener('mouseup', releaseCoin.bind(this));
updateCacheImage(false);
function moveCoin(e){
e.currentTarget.x = e.stageX;
e.currentTarget.y = e.stageY;
stage.update();
createMask(e);
}
function createMask(e) {
if(!pressBool)return;
var xLoc = stage.mouseX-20;
var yLoc = stage.mouseY-30;
mask_mc.graphics.beginFill("FFFFFF").drawEllipse(xLoc, yLoc, 40, 60);
updateCacheImage(true);
}
function updateCacheImage(update){
var w = 361;
if (update) {
mask_mc.updateCache();
} else {
mask_mc.cache(0, 0, w, w);
}
maskFilter = new createjs.AlphaMaskFilter(mask_mc.cacheCanvas);
bg_mc.filters = [maskFilter];
if (update) {
bg_mc.updateCache(0, 0, w, w);
} else {
bg_mc.cache(0, 0, w, w);
}
}
function releaseCoin(e) {
//stage.canvas.style.cursor = "default";
pressBool = false;
updateCacheImage(true);
}
}
// actions tween:
this.timeline.addTween(cjs.Tween.get(this).call(this.frame_0).wait(1));
}).prototype = p = new cjs.MovieClip();
p.nominalBounds = new cjs.Rectangle(385.9,359.4,113.9,113);
// library properties:
lib.properties = {
width: 550,
height: 400,
fps: 24,
color: "#999999",
opacity: 1.00,
manifest: [],
preloads: []
};
})(lib = lib||{}, images = images||{}, createjs = createjs||{}, ss = ss||{}, AdobeAn = AdobeAn||{});
var lib, images, createjs, ss, AdobeAn;
HTML Code:-
<!DOCTYPE html>
<!--
NOTES:
1. All tokens are represented by '$' sign in the template.
2. You can write your code only wherever mentioned.
3. All occurrences of existing tokens will be replaced by their appropriate values.
4. Blank lines will be removed automatically.
5. Remove unnecessary comments before creating your template.
-->
<html>
<head>
<meta charset="UTF-8">
<meta name="authoring-tool" content="Adobe_Animate_CC">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui" />
<meta name="msapplication-tap-highlight" content="no"/>
<title>scratchGame_Canvas</title>
<!-- write your code here -->
<script src="jquery-3.2.1.slim.min.js"></script>
<script src="createjs-2015.11.26.min.js"></script>
<script src="scratchGame_Canvas.js?1497868121984"></script>
<script>
var canvas, stage, exportRoot, anim_container, dom_overlay_container, fnStartAnimation;
var pRatio = window.devicePixelRatio || 1, xRatio, yRatio, sRatio=1;
function init() {
canvas = document.getElementById("canvas");
anim_container = document.getElementById("animation_container");
dom_overlay_container = document.getElementById("dom_overlay_container");
handleComplete();
}
function handleComplete() {
//This function is always called, irrespective of the content. You can use the variable "stage" after it is created in token create_stage.
exportRoot = new lib.scratchGame_Canvas();
stage = new createjs.Stage(canvas);
stage.addChild(exportRoot);
//Registers the "tick" event listener.
fnStartAnimation = function() {
createjs.Ticker.setFPS(lib.properties.fps);
createjs.Ticker.addEventListener("tick", stage);
}
//Code to support hidpi screens and responsive scaling.
function makeResponsive(isResp, respDim, isScale, scaleType) {
var lastW, lastH, lastS=1;
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
function resizeCanvas() {
var w = lib.properties.width, h = lib.properties.height;
var iw = window.innerWidth, ih=window.innerHeight;
pRatio = window.devicePixelRatio || 1, xRatio=iw/w, yRatio=ih/h, sRatio=1;
if(isResp) {
if((respDim=='width'&&lastW==iw) || (respDim=='height'&&lastH==ih)) {
sRatio = lastS;
}
else if(!isScale) {
if(iw<w || ih<h)
sRatio = Math.min(xRatio, yRatio);
}
else if(scaleType==1) {
sRatio = Math.min(xRatio, yRatio);
}
else if(scaleType==2) {
sRatio = Math.max(xRatio, yRatio);
}
}
canvas.width = w*pRatio*sRatio;
canvas.height = h*pRatio*sRatio;
canvas.style.width = dom_overlay_container.style.width = anim_container.style.width = w*sRatio+'px';
canvas.style.height = anim_container.style.height = dom_overlay_container.style.height = h*sRatio+'px';
stage.scaleX = pRatio*sRatio;
stage.scaleY = pRatio*sRatio;
lastW = iw; lastH = ih; lastS = sRatio;
}
}
makeResponsive(true,'both',false,1);
fnStartAnimation();
}
</script>
<!-- write your code here -->
</head>
<body onload="init();" style="margin:0px;">
<div id="animation_container" style="background-color:rgba(153, 153, 153, 1.00); width:550px; height:400px">
<canvas id="canvas" width="550" height="400" style="position: absolute; display: block; background-color:rgba(153, 153, 153, 1.00);"></canvas>
<div id="dom_overlay_container" style="pointer-events:none; overflow:hidden; width:550px; height:400px; position: absolute; left: 0px; top: 0px; display: block;">
</div>
</div>
</body>
</html>
Hope to get response soon.
Thanks.
As I mentioned in the comments, you can transform the coordinates, so your x/y mouse position is not affected by the canvas scaling by responsiveness, and one alternative is to use, in the binded function with the pressmove event (in your case, the function moveCoin()), the globalToLocal() method.
scratchGame_Canvas.js
Function moveCoin()
function moveCoin(e){
var point;
point = stage.globalToLocal(e.stageX, e.stageY);
e.currentTarget.x = point.x;
e.currentTarget.y = point.y;
stage.update();
createMask(e);
}
See also: Drag and drop with easeljs in Animate CC 2017
& MovieClip class (EaselJS API)

jQuery-Knob to control web audio api panning

So I have a panning feature with a basic HTML input range I am using the following javascript code to control the panning:
var x = this.valueAsNumber,
y = 0,
z = 1 - Math.abs(x);
panner2.setPosition(x,y,z);
Any idea how to implement it with jQuery-Knob library? I have done it with volume control using change function and reading in value but panning uses more than one value so unsure how to implement it.
Example implementation. I did this using another formula for equal power panning and it isn't perfect but maybe it can help you understand how to affect variables with the knob plug in.
<div class = "container">
<div id="pad" style=""></div>
<input id="panDial" class="dial" data-min="0" data-max="360" value="0" data-width="100">
</div>
$(function() {
var audioContext = new AudioContext();
var oscillator;
var val;
var x = 0;
var y = 0;
var z = 0;
var xDeg = 0;
var zDeg = xDeg + 90;
var valuePanDial = document.getElementById("panDial").value;
$(".dial").knob({
change: function(valuePanDial) {
xDeg = +valuePanDial;
zDeg = 180 - zDeg;
x = Math.sin(xDeg * (Math.PI / 180));
z = Math.sin(zDeg * (Math.PI / 180));
}
});
$("#pad").on("mousedown", function() {
oscillator = audioContext.createOscillator();
var panner = audioContext.createPanner();
panner.setPosition(x, y, z);
panner.panningModel = 'equalpower';
oscillator.frequency.value = 100;
oscillator.type = "sawtooth";
oscillator.connect(panner); // Connects it to output
panner.connect(audioContext.destination);
oscillator.start(audioContext.currentTime);
})
$("#pad").on("mouseup", function() {
oscillator.stop(audioContext.currentTime);
})
});
.container{
position:relative;
top:30px;
width:700px;
left:40%;
}
#pad {
background-color:orange;
margin-bottom:20px;
opacity:0.8;
border-style:solid;
border-color:grey;
width:200px;
height:100px;
}
#freqDial{
width:10px;
height: 10px;
}

Send an email with attachment and save in Google Drive using Google Apps Script

Hi everyone and thanks a lot for reading this.
I have some code that was based on SendPDF of Jiayao. Original here: SendPDF of Jiayao
I have a Google Spreadsheet that generates a PDF, send email, and save the pdf in Google Drive ( I using Google Apps).
It always worked. However, when I moved to the New Google Drive no longer works.
When I run I get the error:
Request failed http://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=1KWJC2tHk6uxrrIYwaf3GOe5NKsPzQRaYQy2pPmwfx_M&exportFormat=pdf&gid=954198957 retornou o código 401. Resposta truncada do servidor:< HTML > < HEAD > < TITLE >Unauthorized < BODY BGCOLOR="#FFFFFF" TEXT="#000000"> < H1 >Unauthorized Error 401 (use a opção muteHttpExceptions para examinar a resposta completa)
Below, my code:
// Copyright 2010 Jiayao Yu
//
// ORIGINAL See usage and updated version on http://gist.github.com/405466
var TOKEN_CELL = 1;
var EMAIL_CELL = 2;
var BCC_CELL = 3;
var SUBJECT_CELL = 4;
var BODY_CELL = 5;
var SHEET_NAME_CELL = 6;
var SHEET_RELATORIO = 7;
var SPREADSHEET_URL = "http://spreadsheets.google.com/feeds/download/spreadsheets/Export?key=";
var DATA_RELATORIO = 8;
var BUSCA_GID = 9;
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet(),
menuEntries = [ {name: "Enviar relatório", functionName: "sendAsPdf"}];
ss.addMenu("Relatório HRT", menuEntries);
var configSheet = getConfigSheet();
configSheet.getRange(1, TOKEN_CELL).setValue("Auth Token");
configSheet.getRange(1, EMAIL_CELL).setValue("Email");
configSheet.getRange(1, BCC_CELL).setValue("Bcc");
configSheet.getRange(1, SUBJECT_CELL).setValue("Subject");
configSheet.getRange(1, BODY_CELL).setValue("htmlBody");
configSheet.getRange(1, SHEET_NAME_CELL).setValue("Export sheet name");
configSheet.getRange(1, SHEET_RELATORIO).setValue("Relatorio");
configSheet.getRange(1, DATA_RELATORIO).setValue("DatadoRelatorio");
configSheet.getRange(1, BUSCA_GID).setValue("BGID");
}
function sendAsPdf() {
// Pergunta se deseja enviar email
var PerguntaEmail = Browser.msgBox('Enviar Email', 'Deseja enviar email para ' + getConfig(EMAIL_CELL) , Browser.Buttons.YES_NO);
if (PerguntaEmail == 'yes' ) {
var configSheet = getConfigSheet();
var id = SpreadsheetApp.getActiveSpreadsheet().getId();
var sheetName = getConfig(SHEET_NAME_CELL);
var arquivoName = getConfig(SHEET_NAME_CELL) + getConfig(SHEET_RELATORIO);
var dataSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
if (!dataSheet) {
Browser.msgBox("Can't find sheet named:" + sheetName);
return;
}
// Atualiza a data do Relatório na aba Relatorio_Pneumologia
// Browser.msgBox(getConfig(DATA_RELATORIO));
// var formattedDate = Utilities.formatDate(new Date(), "GMT-3", "dd-MM-yyyy");
dataSheet.getRange(3,2).setValue(getConfig(DATA_RELATORIO));
// Logger.log(formattedDate);
// Browser.msgBox(formattedDate);
// Envia EMAIL
var dataSheetIndex = dataSheet.getIndex() - 1;
// Original: var url = SPREADSHEET_URL + id + "&exportFormat=pdf&gid=" + dataSheetIndex;
var url = SPREADSHEET_URL + id + "&exportFormat=pdf&gid=" + getConfig(BUSCA_GID);
var auth = "AuthSub token=\"" + getConfig(TOKEN_CELL) + "\"";
var res = UrlFetchApp.fetch(url, {headers: {Authorization: auth}});
var content = res.getContent();
var responseCode = res.getResponseCode();
if (responseCode != 200 || res.getContentText().indexOf("/ServiceLoginAuth") != -1) {
Logger.log("Fetch url:" + url + " failed with " + responseCode);
Browser.msgBox("Error occurred when exporting spreadsheet to pdf, it might be caused by auth token being expired");
return;
}
var bcc = getConfig(BCC_CELL);
Logger.log("BCC to:" + bcc);
var attachments = [{fileName:arquivoName + ".pdf", content: content, mimeType:"application/pdf"}];
MailApp.sendEmail(getConfig(EMAIL_CELL), getConfig(SUBJECT_CELL),
"", {attachments:attachments, bcc: bcc, htmlBody: getConfig(BODY_CELL)});
Browser.msgBox("Email enviado com sucesso para: " + getConfig(EMAIL_CELL));
// Salvar versao do relatório no Google Drive
var Impressao = Browser.msgBox('Salvar Relatorio', 'Deseja salvar o relatório no Google Drive?', Browser.Buttons.YES_NO);
if (Impressao == 'yes' ) {
// Codigo inspirado em http://stackoverflow.com/questions/12881547/exporting-spreadsheet-to-pdf-then-saving-the-file-in-google-drive
// Salva no Google Drive
var NomedoArquivo = arquivoName + ".pdf"
DocsList.createFile(res).rename(NomedoArquivo);;
Browser.msgBox('Arquivo gravado em seu Google Drive. Pode fechar da planilha.');
}
else { Browser.msgBox('Operação concluída com sucesso. Pode fechar da planilha.')
}
}
// FIM DO THEN do IF se deseja enviar email
else { Browser.msgBox('Ok. Pode fechar da planilha.')
}
// FIM DO IF se deseja enviar email
// FIM DA FUNCAO - sendAsPdf
}
function getConfig(cell) {
var configSheet = getConfigSheet();
return configSheet.getRange(2, cell).getValue();
}
function getConfigSheet() {
var name = "script_config";
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(name);
if (!sheet) {
sheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet(name);
Logger.log("Created sheet " + name);
}
return sheet;
}
I appreciate any suggestions.
The new version of spreadsheets use a different url for file conversion, that's why your script is not working anymore.
You have 2 possible solutions :
Use the advanced drive service as shown in Eric Koleda's answer which can provide multiple export formats
Use the simple getAs('application/pdf') from the Drive service since pdf is the only supported format (for now) and that's what you are using !
The returned value is a blob, you can use it directly to create your file in Drive.