c++ builder Excel Ole Create new worksheet after the last sheet - c++

I want to add a new worksheet not at the beginning but at the end of the worksheet tabs. But i can only manage to get it working at the front.
workSheet = workSheets.OleFunction("Add");
How can i change this line of code to make it add at the end ?

The Worksheets.Add() method has optional Before and After parameters:
Before
An object that specifies the sheet before which the new sheet is added.
After
An object that specifies the sheet after which the new sheet is added.
...
If Before and After are both omitted, the new sheet is inserted before the active sheet.

You need to set After param
Excel::_WorksheetPtr newSheet;
if (const auto sheetsCount = m_book->Worksheets->GetCount(); sheetsCount == 0)
newSheet = m_app->Worksheets->Add();
else
{
IDispatchPtr dispatch = m_app->Worksheets->GetItem(sheetsCount); // Number of sheet, not index
newSheet = m_app->Worksheets->Add(vtMissing, dispatch.GetInterfacePtr(), 1);
}
return newSheet;

Related

Simple relative cell referencing in google code

I have made this virtual inventory with buttons that copy and paste values to various sheets for different types of reports. The code might not be optimal I am not much of a programmer but I'm trying my best. now I have the same button in multiple places and I want it to copy values in cells relative to the position of the button itself but I am not sure how to reference a cell in a relative manner in the getRange fucntion.
here is the code:
function Go() {
var ss = SpreadsheetApp.getActiveSpreadsheet ();
var sheet = SpreadsheetApp.getActiveSheet();
var destSheet = ss.getSheetByName("Fiche");
var lastRow = destSheet.getLastRow();
var source = ss.getRange ('(rowid-3)(colid)');
var checkbox = sheet.getRange (3,3);
var destColumn = ss.getRange ('B10').getValues ();
source.copyTo(destSheet.getRange(lastRow + 1,1), {contentsOnly: true});
if (checkbox.getValue() == 'vrai' ) {
var source = ss.getRange ('B9');
source.copyTo(destSheet.getRange(lastRow + 1, destColumn), {contentsOnly: true});
source.copyTo(destSheet.getRange(lastRow + 1, 2), {contentsOnly: true});
}
else {
var nombre = ss.getRange ('D5').getValues() ;
destSheet.getRange(lastRow + 1, destColumn).setValue(nombre);
destSheet.getRange(lastRow + 1, 2).setValue(nombre)
}
I want all (B10),(B9), etc. format cells to be replaced with relative cell positons. I have tried with (colID)(rowID) but it doesn't seem to work
I believe your goal as follows.
You want to retrieve the cell coordinate when a button on Spreadsheet is clicked.
Modification points:
Unfortunately, in the current stage, when a button on Spreadsheet is clicked, there are no methods for directly retrieving the information where button is clicked.
So when you want to use the button on Spreadsheet, if you want to retrieve the information, it is required to prepare each script for each button. But I thought that this might be different from the direction you expect.
In this answer, in order to retrieve the information where the button is clicked, I would like to propose the following 2 patterns as the workarounds. In these patterns, the event object is used. By this, the information of the button can be retrieved. This is used.
Pattern 1:
In this pattern, a cell is used as the button using the simple trigger of OnSelectionChange. When the cell "B3" is used as the button like above image, the script is as follows.
Sample script:
In this script, for example, when you want to use the cell "B3" of "Sheet1" as the button, please set "B3" to buttonRanges. And, set sheet.getSheetName() != "Sheet1". When when you want to use the cell "B3" and "B4" as the button, please set "B3" and "B4" to buttonRanges.
function onSelectionChange(e) {
const range = e.range;
const sheet = range.getSheet();
const buttonRanges = ["B3"];
if (sheet.getSheetName() != "Sheet1" || !buttonRanges.includes(range.getA1Notation())) return;
const row = range.getRow(); // This is the row number.
const column = range.getColumn(); // This is the column number.
}
In this case, when the cell "B3" is clicked, this script is run. And row and column are the row and column number of the cell.
Because the cell is used as the button, you can put the value to the cell.
Pattern 2:
In this pattern, a checkbox is used as the button using the OnEdit trigger. When the cell "B3" is used as the button like above image, the script is as follows.
Sample script:
In this script, for example, when you want to use the cell "B3" of "Sheet1" as the button, please set "B3" to buttonRanges. And, set sheet.getSheetName() != "Sheet1". When when you want to use the cell "B3" and "B4" as the button, please set "B3" and "B4" to buttonRanges.
function onEdit(e) {
const range = e.range;
const sheet = range.getSheet();
const buttonRanges = ["B3"];
if (sheet.getSheetName() != "Sheet1" || !buttonRanges.includes(range.getA1Notation()) || !range.isChecked()) return;
const row = range.getRow(); // This is the row number.
const column = range.getColumn(); // This is the column number.
}
In this case, when the checkbox is checked, the script is run. When the checkbox is unchecked, the script is not run.
Because the checkbox is used as the button, you cannot see the text in the cell.
References:
Simple Triggers
Event Objects
Related question
Button change text display every after click
This question is for achieving the switching button.

Transactions in Google Sheet - Move value from, to

I'm trying to make a document to manage my finances on google sheet, actually, I would like to be able to track the transactions I make between my accounts.
I made this sheet to be able to sum things up.
Actually, I would be able to tell the document i'm making a transaction from - to (in that case, from content 1 to content 3) and to add a new value.
I don't know how to tell google sheet to "move" 25 from content 1 to content 3 or any other content.
Thanks for the precious help.
You can use an Apps Script onEdit trigger so fire the transactions, and use checkboxes to track which transaction should be fired, so that the transaction takes place whenever the corresponding checkbox is checked.
First, add the checkboxes to the transaction rows by selecting the appropriate cells and click Insert > Checkbox.
Then, open the script bound to your spreadsheet by selecting Tools > Script editor, copy the following function, and save the project. Now every time a checkbox is checked, the corresponding transaction takes place in B2:E3, and when it is unchecked the transaction gets undone (the from and the to exchange places, and the money goes the other way):
function onEdit(e) {
var range = e.range;
var col = range.getColumn();
var row = range.getRow();
var checkbox = e.value;
var sheet = range.getSheet();
if (col === 6 && row > 8) {
var from = sheet.getRange(row, 3).getValue();
var to = sheet.getRange(row, 4).getValue();
var value = sheet.getRange(row, 5). getValue();
var valuesToUpdate = sheet.getRange("B2:E2").getValues();
var fromIndex = valuesToUpdate[0].findIndex(contents => contents === from);
var toIndex = valuesToUpdate[0].findIndex(contents => contents === to);
var fromRange = sheet.getRange(3, fromIndex + 2);
var toRange = sheet.getRange(3, toIndex + 2);
if (checkbox === "TRUE") { // MAKE TRANSACTION
fromRange.setValue(fromRange.getValue() - value);
toRange.setValue(toRange.getValue() + value);
} else if (checkbox === "FALSE") { // UNDO TRANSACTION
fromRange.setValue(fromRange.getValue() + value);
toRange.setValue(toRange.getValue() - value);
}
}
}
This function will fire every time the spreadsheet is edited, but you only want to update the transaction summary whenever the edited cell is a checkbox and this checkbox is checked. The function is checking for that, using the information passed to the onEdit function through the event object (e), which contains information on the edited cell (its value, its range, etc.):
Reference:
onEdit(e)
Event Objects: Edit

Is there any way to add a template doc at top of an another google document using google scripting?

I am trying to add a template doc into an existing google doc.The template is being added, but next time when i am trying to add the template again the template is appending at the bottom of the existing google doc but i want to insert the template at the top.
You can do this by getting the Body of one document and appending its child Elements to the current document.
function addtemplate() {
var thisDoc = DocumentApp.getActiveDocument();
var thisBody = thisDoc.getBody();
var templateDoc = DocumentApp.openById(''); //Pass in id of doc to be used as a template.
var templateBody = templateDoc.getBody();
for(var i=0; i<templateBody.getNumChildren();i++){ //run through the elements of the template doc's Body.
switch (templateBody.getChild(i).getType()) { //Deal with the various types of Elements we will encounter and append.
case DocumentApp.ElementType.PARAGRAPH:
thisBody.appendParagraph(templateBody.getChild(i).copy());
break;
case DocumentApp.ElementType.LIST_ITEM:
thisBody.appendListItem(templateBody.getChild(i).copy());
break;
case DocumentApp.ElementType.TABLE:
thisBody.appendTable(templateBody.getChild(i).copy());
break;
}
}
return thisDoc;
}
It sounds like your goal is to choose the position of the document where the content is added?
One option is to add the template at your current cursor location.
In the example below I have two functions. The first function creates a menu in Google Docs when I open the document (usually a few seconds delay).
The second function attempts to identify the position of my cursor. If it's successful it will insert the date at my cursor position.
Since I've created a menu item I don't have to go to the script editor to trigger this function.
function onOpen() {
// Add a menu item in Google Docs.
DocumentApp.getUi().createMenu('Insert Menu')
.addItem('Insert Current Date', 'insertCurrentDate')
.addToUi();
}
function insertCurrentDate() {
var cursor = DocumentApp.getActiveDocument().getCursor();
if (cursor) {
// Attempt to insert text at the cursor position. If insertion returns null,
// then the cursor's containing element doesn't allow text insertions.
var date = Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd");
var element = cursor.insertText(date);
if (element) {
element.setBold(true);
} else {
DocumentApp.getUi().alert('Document does not allow inserted text at this location.');
}
} else {
DocumentApp.getUi().alert('Cannot find a cursor in the document.');
}
}
It's also possible that you want to clear the previous template before pasting the new one in? You can do that with the clear() function and then run the rest of your code.
body.clear()

Why does this code not set the background color for a cell (Aspose Cells)?

I need a cell to have a light blue background color; I have code that works in another sheet, but the same exact code (except for the names of the vars and column index val):
Style styleShipVariance = null;
CellsFactory cfShipVariance = new CellsFactory();
Cell ShipVarianceCell = customerWorksheet.Cells[0, SHIPVARIANCE_COL];
ShipVarianceCell.PutValue("Ship Variance");
styleShipVariance = cfShipVariance.CreateStyle();
styleShipVariance.HorizontalAlignment = TextAlignmentType.Left;
styleShipVariance.Font.Name = fontForSheets;
styleShipVariance.Font.IsBold = true;
styleShipVariance.Font.Size = 11;
styleShipVariance.ForegroundColor = Color.LightBlue;
styleShipVariance.Pattern = BackgroundType.Solid;
ShipVarianceCell.SetStyle(styleShipVariance);
...does not work on the other sheet. The value ("Ship Variance") is displayed in that cell, but the color is not being applied.
Why would this not work? What is missing?
Note: I also tried adding this:
var flag = new StyleFlag
{
CellShading = true,
FontName = true,
FontSize = true,
FontColor = true,
FontBold = true,
NumberFormat = true
};
...and changing the last line above to:
ShipVarianceCell.SetStyle(styleShipVariance, flag);
...but it made no difference.
UPDATE
I am saving as xlsx:
var filename = String.Format(#"{0}\{1} - Fill Rate - {2}.xlsx", sharedFolder, _unit, fromAsYYYYMMDD);
if (File.Exists(filename))
{
File.Delete(filename);
}
workBook.Save(filename, SaveFormat.Xlsx);
UPDATE 2
I just noticed that the vals are also not being bolded or left-aligned. The text values themselves are being assigned, but none of the formatting is...
UPDATE 3
Why it was necessary, I don't know, but by adding the colorizing code AFTER the data rows were added to the sheet, it works now.
Well, normally it should work fine. But if you are saving to an XLS file (instead of XLSX file), the light blue background color might not be applied so, you got to add to MS Excel color palette first via the line of code:
e.g
Sample code:
.........
workbook.ChangePalette(Color.LightBlue, 55);
Anyways, we need your template Excel file, so we could evaluate your issue precisely and test to apply the color to the cell on our side and guide you appropriately. I think you may follow up your thread in the Aspose.Cells forums.
I am working as Support developer/ Evangelist at Aspose.

Get ID of excel worksheet in focus using OLE

Using C++ and OLE, how might I go about obtaining the ID of the worksheet that is currently in focus?
For example, I have the following code:
Variant excelSheets;
Variant excelSheet;
excelSheets.OleProcedure("Add");
excelSheet= excelSheets.OlePropertyGet("Item", 1);
I would like to add a sheet and then get the sheet that was just added so that I may add content. The above code only works if the user doesn't shift focus away from the sheet which is at the far left.
Seth
I ended up using OlePropertyGet( "ActiveSheet" ); because when you add a sheet it becomes the ActiveSheet and you can work with it from there. I put an example of what I did below:
Variant excelApp;
Variant excelBooks;
Variant excelWorkBook;
Variant excelSheet;
Variant excelSheets;
try
{
mExcelApp = Variant::GetActiveObject("Excel.Application");
}
catch(EOleSysError& e)
{
mExcelApp = Variant::CreateObject("Excel.Application"); //open excel
}
catch(...)
{
throw;
}
mExcelApp.OlePropertySet("ScreenUpdating", true);
excelBooks = mExcelApp.OlePropertyGet("Workbooks");
excelWorkBook = excelBooks.OlePropertyGet("Item",1);
// a worksheet is added which becomes the active sheet
excelSheets.OleProcedure( "Add" );
excelSheet = excelWorkBook.OlePropertyGet( "ActiveSheet" );