There was a problem.
I create worksheet in library EXCELJS
function save_export(){
var workbook = new ExcelJS.Workbook();
var worksheet = workbook.addWorksheet('sheet', {
pageSetup:{paperSize: 9, orientation:'portrait',fitToPage: true,fitToHeight : 99 , fitToWidth : 1, horizontalCentered: true}
});
var tfoot = [];
$(element).each(function(index_tfoot, element_tfoot) {
$($(element_tfoot).find("#tfoot tr")).each(function(index_tr, element_tr) {
$(this.cells).each(function(index_td, element_td) {
tfoot.push($(element_td).text());
});
var row_foot = worksheet.addRow(tfoot);
row_foot.eachCell(function(cell,rowNumber) {
cell.font = { name: 'Verdana', size: 11};
cell.alignment = {horizontal: 'center' };
cell.border = {
top: { style: "thin" },
left: { style: "thin" },
bottom: { style: "thin" },
right: { style: "thin" }
};
<!-- if(cell._value.model.value === 'ИТОГО'){ -->
<!-- var c = 'A'; -->
<!-- var r = cell._row._number; -->
<!-- var sum = c+r; -->
<!-- worksheet.mergeCells(sum + ': B31'); -->
<!-- } // ПОЛУЧИЛ ИТОГО -->
});
tfoot = [];
});
});
});
workbook.xlsx.writeBuffer().then(function (data) {
var blob = new Blob([data], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
});
saveAs(blob, "Исходная выборка.xlsx");
});
};
when I merge cells, my merged rows over cells as in the screenshot "before". You see what number 238 disappear.
I need the cells to move.
[1]: https://i.stack.imgur.com/kyquZ.png - before
[2]: https://i.stack.imgur.com/0DeRc.png - after
How we see in screenshots, cells merge and value disappear ((
need to shift(
I have faced the same problem.The data needs to be added after merging the cells. Please refer the documentation https://github.com/exceljs/exceljs#merged-cells
Related
i have a for loop adding rows and cells. I want these cells to have only bottom border, thickness 1pt and black color. What is the best way to do this? the documentation is lacking examples
for (var r = 0; r < rowdata.length; r++) { //loop through data for each row
var newrow = table.insertTableRow(1+r)
//add cells and values
var cell1 = newrow.appendTableCell(rowdata[r][0])
var cell2 = newrow.appendTableCell(rowdata[r][1])
//align cell text to center
var cellStyle = {};
cellStyle[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT] = DocumentApp.HorizontalAlignment.CENTER;
cell1.getChild(0).asParagraph().setAttributes(cellStyle)
cell2.getChild(0).asParagraph().setAttributes(cellStyle)
//set bottom border line width to 1pt, line color to black
//set the other borders line width to 0pt
???
}
I believe your goal is as follows.
When the rows are appended, you want to set the bottom border as 1 pt width and black color, and want to set the other borders as 0 pt width.
In the current stage, it seems that unfortunately, the Google Document service (DocumentApp) cannot manage each border. But, fortunately, when Docs API is used, your goal can be achieved. In this answer, I would like to propose achieving your goal using Docs API. When your script is modified it becomes as follows.
Modified script:
Before you use this script, please enable Google Docs API at Advanced Google services.
function myFunction() {
var doc = DocumentApp.getActiveDocument(); // Please set your Document.
var body = doc.getBody();
var table = body.getTables()[0]; // Please set your table.
var rowdata = [[,,,],[,,,],,,]; // Please set your values.
// --- This is your showing script.
for (var r = 0; r < rowdata.length; r++) {
var newrow = table.insertTableRow(1 + r);
var cell1 = newrow.appendTableCell(rowdata[r][0]);
var cell2 = newrow.appendTableCell(rowdata[r][1]);
var cellStyle = {};
cellStyle[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT] = DocumentApp.HorizontalAlignment.CENTER;
cell1.getChild(0).asParagraph().setAttributes(cellStyle);
cell2.getChild(0).asParagraph().setAttributes(cellStyle);
}
// ---
doc.saveAndClose();
var docId = doc.getId();
var i = body.getChildIndex(table);
var index = Docs.Documents.get(docId).body.content[i + 1].startIndex;
var requests = [{ updateTableCellStyle: { tableCellStyle: { borderRight: { dashStyle: "SOLID", width: { magnitude: 0, unit: "PT" }, color: { color: {} } }, borderLeft: { dashStyle: "SOLID", width: { magnitude: 0, unit: "PT" }, color: { color: {} } } }, tableStartLocation: { index }, fields: "borderRight,borderLeft" } }];
Docs.Documents.batchUpdate({ requests }, doc.getId());
}
When this script is run, several rows are appended to the table on Document, and the width of vertical borders is changed to 0 pt. By this, only the bottom borders are shown.
References:
Method: documents.get
Method: documents.batchUpdate
UpdateTableCellStyleRequest
Added:
From your following reply,
that is what i am looking for with one difference. The table i am appending to already has some rows that i want to remain unchanged concerning their border style. I want to apply your code to the newly added rows only!
When you wanted to reflect the above request body to the appended rows, how about the following modification?
In your showing script, you are using var newrow = table.insertTableRow(1 + r);. In this case, the rows are put from the 2nd row. Using this script, how about the following sample script?
Sample script:
function myFunction() {
var doc = DocumentApp.getActiveDocument(); // Please set your Document.
var body = doc.getBody();
var table = body.getTables()[0]; // Please set your table.
var rowdata = [[,,,],[,,,],,,]; // Please set your values.
// --- This is your showing script.
for (var r = 0; r < rowdata.length; r++) {
var newrow = table.insertTableRow(1 + r);
var cell1 = newrow.appendTableCell(rowdata[r][0]);
var cell2 = newrow.appendTableCell(rowdata[r][1]);
var cellStyle = {};
cellStyle[DocumentApp.Attribute.HORIZONTAL_ALIGNMENT] = DocumentApp.HorizontalAlignment.CENTER;
cell1.getChild(0).asParagraph().setAttributes(cellStyle);
cell2.getChild(0).asParagraph().setAttributes(cellStyle);
}
// ---
doc.saveAndClose();
var docId = doc.getId();
var i = body.getChildIndex(table);
var index = Docs.Documents.get(docId).body.content[i + 1].startIndex;
// I modified this request body.
var requests = [{ updateTableCellStyle: { tableCellStyle: { borderRight: { dashStyle: "SOLID", width: { magnitude: 0, unit: "PT" }, color: { color: {} } }, borderLeft: { dashStyle: "SOLID", width: { magnitude: 0, unit: "PT" }, color: { color: {} } } }, tableRange: { tableCellLocation: { tableStartLocation: { index }, rowIndex: 1 }, rowSpan: rowdata.length, columnSpan: rowdata[0].length }, fields: "borderRight,borderLeft" } }];
Docs.Documents.batchUpdate({ requests }, doc.getId());
}
When this script is run, the vertical lines are removed from the appended rows from the 2nd row.
let myChart = null;
function draw(){
const labels = [];
for (var i = 0; i < stats.length; i++) {
labels.push(legend[i]);
}
const data = {
labels: labels,
datasets: [{
backgroundColor: ['rgb(204,0,0)', 'rgb(241,194,50)', 'rgb(41,134,204)', 'rgb(106,168,79)', 'rgb(255,62,153)'],
data: stats,
}]
};
const config = {
type: 'doughnut',
data: data,
options: {
radius: 200,
hoverOffset: 30,
aspectRatio: 1,
maintainAspectRatio: false,
responsive: false,
}
};
if (myChart !== null) {
myChart.destroy();
}
myChart = new Chart(document.getElementById('defaultCanvas0'), config);
}
When i run this code my chart just keeps flickering and drawing itself over and over again with a new id each time. I need to be able to destroy my original chart before drawing a new one
This is what console.log displays:
Edit:
function HealthStudy() {
//name for the visualisation to appear in the menu bar
this.name = "Health study";
//each visualisation must have a unique ID with no special characters
this.id = "Health-study";
//property to represent whether stats has been loaded
this.loaded = false;
// Preload the stats. This function is called automatically by the
// gallery when a visualisation is added.
this.preload = function () {
var self = this;
this.stats = loadTable(
'./data/health/causes-of-death.csv', 'csv', 'header',
// Callback function to set the value
// this.loaded to true.
function (table) {
self.loaded = true;
});
};
this.setup = function () {
if (!this.loaded) {
console.log('stats not yet loaded');
return;
}
// Create a select DOM element.
this.select = createSelect();
this.select.position(800, 380);
// Fill the options with all country names.
var countries = this.stats.columns;
// First entry is empty.
for (let i = 1; i < countries.length; i++) {
this.select.option(countries[i]);
}
};
this.destroy = function () {
this.select.remove();
};
// Create a new donut object.
this.donut = new Donut(width / 2, height / 2, width * 0.4);
this.draw = function () {
if (!this.loaded) {
console.log('stats not yet loaded');
return;
}
// Get the value of the country we're interested in from the
// select item.
var country = this.select.value();
// Get the column of raw stats for country.
var col = this.stats.getColumn(country);
// Convert all stats strings to numbers.
col = stringsToNumbers(col);
// Copy the row labels from the table (the first item of each row).
var legend = this.stats.getColumn(0);
// Colour to use for each category.
var colours = ['#CC0000', '#55a5f2', '#4dff00', '#f4e410', '#6a329f'];
// Make a title.
var title = 'Top 5 causes of death in ' + country;
// Draw the Donut!
this.donut.draw(col, legend, colours, title);
Auto-complete is not getting fired when pressing white-space in the editor, Is there an option to fire Autocomplete when white space is pressed?
Please have a look at this demo:
[jsfiddle] https://jsfiddle.net/xbaha/cbfe6tx4/53/
I want the auto complete to be fired when i type "my name is " (note there is a space after "is"), then using onchange event i added the suggestions that should pop up, but it does not work, i must type a letter character so that autocomplete is getting fired.
is there a solution for this?
Instead of using enableLiveAutocomplete option you can use a custom handler for afterExec event https://github.com/ajaxorg/ace/blob/v1.4.7/lib/ace/ext/language_tools.js#L149
var editor;
var fieldsList = [];
function initAceEditor() {
editor = ace.edit("aceEditor", {
theme: "ace/theme/solarized_light",
mode: "ace/mode/text",
showPrintMargin: false,
fontSize: "24px",
minLines: 3,
maxLines: 8,
wrap: true,
// do not use live autocomplete since we want to invoke more often
// enableLiveAutocompletion: true,
enableBasicAutocompletion: true,
});
var langTools = ace.require("ace/ext/language_tools");
var stepLineCompleter = {
getCompletions: function(editor, session, pos, prefix, callback) {
var completions = [];
console.log('before foreach....', this.fields, fieldsList);
var cursor = session.selection.cursor
var line = session.getLine(cursor.row).slice(0, cursor.column - prefix.length)
var fieldsList
if (line.endsWith("name is ")) {
fieldsList = ["bob", "james", "alex", "jimmy"];
} else {
fieldsList = ["my name is", "completion2", "completion3", "one more"]
}
fieldsList.forEach(function(w) {
completions.push({
value: w,
});
});
callback(null, completions);
}
}
langTools.setCompleters([stepLineCompleter]);
langTools.addCompleter(stepLineCompleter);
var Autocomplete = ace.require("ace/autocomplete").Autocomplete
var doLiveAutocomplete = function(e) {
var editor = e.editor;
var hasCompleter = editor.completer && editor.completer.activated;
var session = editor.session
var cursor = session.selection.cursor
var line = session.getLine(cursor.row).slice(0, cursor.column)
// We don't want to autocomplete with no prefix
if (e.command.name === "backspace") {
// do not hide after backspace
} else if (e.command.name === "insertstring") {
if (!hasCompleter) {
// always start completer
var completer = Autocomplete.for(editor);
// Disable autoInsert
completer.autoInsert = false;
completer.showPopup(editor);
}
}
};
editor.commands.on('afterExec', doLiveAutocomplete);
}
initAceEditor()
#aceEditor {
position: absolute;
top: 10%;
right: 0;
bottom: 30%;
left: 0;
}
<script src="https://rawgithub.com/ajaxorg/ace-builds/master/src/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="https://rawgithub.com/ajaxorg/ace-builds/master/src/ext-language_tools.js" type="text/javascript" charset="utf-8"></script>
<div id="aceEditor"></div>
I am showing data response from server in a popup. I am trying to download that data as pdf using pdfmake plugin. Data is generated as pdf, but the challenging is I need to generate pdf file just like in the html page. I am attaching a sample data from the html popup.
My JS code
$scope.download_pdf = function(questions,temptitle,extid,info){
var content = [];
var today = moment().format('lll');
var docDefinition = {
content: content,
styles: {
header: {
fillColor: '#6faadc',
color:'#18b0ff',
fontSize:16,
bold: true,
margin:[5,35,0,0]
},
questionStyle: {
width: '100%',
fontSize: 13,
bold: true,
margin:[5,20,20,0],
},
answerStyle: {
width: '100%',
fontSize: 13,
margin:[20,10,0,0],
color:'#57585a'
},
date: {
color:'#57585a'
}
}
};
content.push({image:compLogo,width:100,margin:[5,0,0,0],alignment: 'left' });
content.push({text: today,style: 'date',regular: true,fontSize: 10,margin:[0,-20,0,0],alignment: 'right'})
content.push({text: $scope.labelForexternalId+": "+extid,style: 'date',regular: true,fontSize: 10,margin:[5,80,0,0],alignment: 'left'})
content.push({text: $scope.labelForadditionalInfo+": "+info,style: 'date',regular: true,fontSize: 10,margin:[5,10,0,0],alignment: 'left'})
content.push({ text: temptitle, style: 'header' })
if($scope.QuestTemplateAnswer[0]['isApproved'] == true || $scope.isVerified == true){
var validatedBy = "Approved by: "+$scope.QuestTemplateAnswer[0]['validatedBy']+ " on "+moment($scope.QuestTemplateAnswer[0]['updatedAt']).format('ll');
content.push({text: validatedBy,style: 'date',regular: true,fontSize: 9,margin:[5,0,0,0]})
}
for(var i = 0; i < questions.length; i++){
var index = i + 1
content.push({ text: index+'. '+questions[i].question, style: 'questionStyle' })
if(questions[i].answers){
for(var j = 0; j < questions[i].answers.length; j++){
content.push([{ text: questions[i].answers[j].answer, style: 'answerStyle' }])
}
}else if(questions[i].answer){
content.push({ text: questions[i].answer, style: 'answerStyle' })
}else if(questions[i].files && questions[i].files.length > 0){
for(var k = 0; k < questions[i].files.length; k++){
content.push({image:$scope.content_images[i][k],width:300,height:200,margin:[20,10,0,0],alignment: 'left'})
content.push({ text: questions[i].files[k].caption, style: 'answerStyle' })
}
}
if(questions[i].subQuestion){
content.push({ text: index+'. '+questions[i].subQuestion.question, style: 'questionStyle', margin:[15,20,20,0]})
if(questions[i].subQuestion.answers){
for(var j = 0; j < questions[i].answers.length; j++){
content.push([{ text: questions[i].subQuestion.answers[j].answer, style: 'answerStyle', margin:[30,20,20,0]}])
}
}else if(questions[i].answer){
content.push({ text: questions[i].subQuestion.answer, style: 'answerStyle', margin:[30,10,20,0]})
}
}
}
// pdfMake.createPdf(docDefinition).open();
pdfMake.createPdf(docDefinition).download(temptitle+".pdf");//Create PDF
}
I need generate pdf file exactly like the image. Please guide me how to do this.
Thanks,
Sankar.
What you want is to screenshot the popup and make it a pdf? If that is here is an example that works fine with me:
1) First you need to import :
<!--html2canvas-->
<script type="text/javascript" src="~/Scripts/html2canvas.js"></script>
<!--PdfMAKER-->
<script type="text/javascript" src="~/Scripts/pdfmake.min.js"></script>
<script src="//kendo.cdn.telerik.com/2016.3.914/js/kendo.all.min.js"></script>
2) In your html code it should be like this:
<div id="exportthis">
<!--ALL YOUR HTML CODE OF YOUR POPUP-->
</div>
3)In your javascript code:
function imprimir() {
html2canvas(document.getElementById('exportthis'), {
onrendered: function (canvas) {
var data = canvas.toDataURL();
var docDefinition = {
content: [{
image: data,
width: 500,
}]
};
pdfMake.createPdf(docDefinition).download("Titulo.pdf");
}
});
}
DESCRIPTION:
What i do is to load de with the info and de style i want and then i have a button that execute the function print().
Let me know if it works for you and if it doesn't i will check my example because maybe it forget something.
I am using the highstock charts library for a set of 4 charts. I used the options object and literal notation as described HERE. The 4 charts have the same set of options by default (the renderCharts() function in the code bellow is responsible for that) and there is a charts type picker (the setChatType() function ) with the help of which the user can change the chart type.
See all togheter HERE.
Can anyone please tell me the cause of and solution for this error in the console:
"Uncaught TypeError: Cannot read property 'addPoint' of undefined"?
Thank you!
/* ============ CHARTS OPTIONS BEGIN ============ */
var options = {
chart : {
zoomType: 'x',
events : {
load : function () {
// set up the updating of the chart each second
var series = this.series[0];
setInterval(function () {
var x = (new Date()).getTime();
var y = Math.round(Math.random() * 100);
series.addPoint([x, y]);
}, 1000);
}
}
},
rangeSelector: {
buttons: [{
count: 1,
type: 'minute',
text: '1M'
}, {
count: 5,
type: 'minute',
text: '5M'
}, {
type: 'all',
text: 'All'
}],
inputEnabled: false,
selected: 0
},
title : {
text: null
},
exporting: {
enabled: false
},
// Disable navigator
navigator : {
enabled : false
},
series : [{
name : '',
data : (function () {
// generate an array of random data
var data = [],
time = (new Date()).getTime(), i;
for (i = -999; i <= 0; i = i + 1) {
data.push([
time + i * 1000,
Math.round(Math.random() * 100)
]);
}
return data;
}())
}]
}
/* ============ CHARTS OPTIONS END ============ */
/* ============ DRAW CHARTS BEGIN ============ */
function renderCharts(){
$('div.chart-container').each(function(){
var chartId = $(this).attr('id');
var chartIdParts = chartId.split('-');
var chartIdentifier = chartIdParts[1];
//Set chart options dinamically
var chartId = "chart" + chartIdentifier;
var chart = $('#' + chartId);
var renderTo = "chartcontainer-" + chartIdentifier;
//Render Charts for each aech container
options.chart.renderTo = renderTo;
options.chart.type = 'line';
var chart = new Highcharts.StockChart(options);
});
}
function setChatType(){
// Show types list (piker)
$('.current-type').on('click', function(){
$(this).parents('div.chart-options').find('ul.type ul').addClass('clicked');
});
$('.chart-options ul ul li a').on('click', function(){
//Get piked chart type
var type = $(this).parent('li').attr('data-chart-type');
// For text and Title Capitalization
var textAndTitle = type.replace(/^[a-z]/, function(m){ return m.toUpperCase() });
// Show piked type in picker
var currSetClass = 'current-type ' + type;
$(this).parents('.chart-options').find('.current-type')
.text(textAndTitle)
.attr({
class : currSetClass,
title: textAndTitle
});
// Then Hide the types list
$('.chart-options ul ul').removeClass('clicked');
//Identify current chart container by ID
var chartCtnId= $(this).parents('div.chart').find('.chart-container').attr('id');
// Render chart again with new type
options.chart.renderTo = chartCtnId;
options.chart.type = type;
var chart = new Highcharts.StockChart(options);
});
}
/* ============ DRAW CHARTS END ============ */
$(document).ready(function(){
$("article.grid:even").addClass('left')
$("article.grid:odd").addClass('right');
// Draw charts
renderCharts();
// Set/change chart type
setChatType();
});
The solution, suggested by Pawel:
instead of
var chart = new Highcharts.StockChart(options);
use
var chart = new Highcharts.StockChart( $.extend(true, {}, options) );