Missing method in JavaScript API for Excel: copy a sheet - excel

Since there is no way to cancel the changes made by an add-in, we need to provide users with backup options.
The current version of JavaScript API for Excel doesn't have a method for copying a sheet with its data and formatting.
Does anyone know of any workarounds or plans for adding such method?

There are indeed currently no way easy way of duplicating a worksheet and so feel free to request it on the Office Extensibility Platform's UserVoice. While such an API may be coming in the future, you could in the meantime add a new worksheet using worksheetCollection.add(), grab a worksheet's used range using the worksheet.getUsedRange() method and copy its values to another sheet.
Your code would then look something like this :
function duplicateSheet(worksheetName) {
Excel.run(function(ctx) {
var worksheet = ctx.workbook.worksheets.getItem(worksheetName);
var range = worksheet.getUsedRange();
range.load("values", "address");
var newWorksheet = ctx.workbook.worksheets.add(worksheetName + " - Backup");
return ctx.sync().then(function() {
var newAddress = range.address.substring(range.address.indexof("!") + 1);
newWorksheet.getRange(newAddress).values = range.values;
}).then(ctx.sync);
});
}
Let me know how that works out for you.
Gabriel Royer - Developer on the Office Extensibility Team, MSFT

Related

Cannot find Excel in Javascript Chart API

I was trying to use this Microsoft tutorial Excel Chart Add-in - Javascript API
In the first example, it has the code
Excel.run(function (context) {
var sheet = context.workbook.worksheets.getItem("Sample");
var dataRange = sheet.getRange("A1:B13");
var chart = sheet.charts.add("Line", dataRange, "auto");
chart.title.text = "Sales Data";
chart.legend.position = "right"
chart.legend.format.fill.setSolidColor("white");
chart.dataLabels.format.font.size = 15;
chart.dataLabels.format.font.color = "black";
return context.sync();
}).catch(errorHandlerFunction);
If I run the code example I receive 2 errors. One that it cannot find excel from
Excel.run
And the errorhandler function is not defined, which appears to be correct.
Are these typos in new Microsoft documents? If not what have I got to change?
Version: excel 365 online build 16.0.13615.35052
2 things that you need to make sure you have in order to run this code succesfully.
Please add the errorHandlerFunction this could be be as easy as this:
function errorHandlerFunction(e ){
console.log("exception" + e );
}
Make sure you have a worksheet named "Sample". Make sure its exactly that name without trailing blank spaces.

Excel Office Add-In API Worksheet Protection Password

I have a question relating to Excel's worksheet protection...
The context is that I need to have different worksheets available for different user groups to edit but all groups must at least see all sheets e.g. usergroup1 can edit sheets two and three and parts of sheet one, usergroup2 can edit only sheet one.
I am able to set the FormatProtection (range.format.protection.locked = false;) accordingly and WorksheetProtection (worksheet.protection.protect();) to enable this but I don't appear to have the ability to set a password through the API against the Worksheet Protection? This means for example, that either group can simply click the Unprotect Sheet option in the review ribbon and edit the sheets that I don't want them to.
I've tried going through the below documentation but to no avail unfortunately.
http://dev.office.com/reference/add-ins/excel/worksheetprotection
https://github.com/OfficeDev/office-js-docs/blob/master/reference/excel/worksheetprotection.md
As an example, here is a function that I'd like to complete:
function CopyWorksheet() {
var newAddress;
Excel.run(function (ctx) {
var worksheet = ctx.workbook.worksheets.getActiveWorksheet();
var range = worksheet.getUsedRange();
range.load();
// insert new worksheet
var newWorksheetName = "Copied_Sheet";
var newWorksheet = ctx.workbook.worksheets.add(newWorksheetName);
return ctx.sync().then(function () {
// copy the old values to the new worksheet
newAddress = range.address.substring(range.address.indexOf("!") + 1);
newWorksheet.getRange(newAddress).values = range.values;
newWorksheet.getRange(newAddress).formulas = range.formulas;
newWorksheet.getRange(newAddress).text = range.text;
// protect both worksheets
worksheet.protection.protect();
newWorksheet.protection.protect();
// requirement here to set a password so that no one can
// edit the worksheets by selecting 'Unprotect Sheet' in excel
// ...
})
.then(ctx.sync)})
.catch(function(error) {
console.log("Error: " + error);
});
}
Currently, I'm using Excel 2016 (desktop version). Is this possible to implement or have I missed some functionality that exists which can achieve the same result?
Thanks for your help.
Password-protection is not available in our APIs. You can protect the sheet to avoid casual edits, but you can't password-protect. The reason is that password-protection is not available on all endpoints (IIRC, there was an issue with Excel Online).
If you want to file a suggestion bug on UserVoice, you can see if we'd consider doing password-protection as a Desktop-only API. We have so far avoided doing those in Excel, but I do know that Word has done a few "WordApiDesktop" APIs. So depending on how much it's blocking your (and others') scenario, that might be an option. In which case you'd be able to password-protect and unprotect on desktop, but wouldn't be able to take those actions online.
There is an update for this issue: we now support password protection. Check https://learn.microsoft.com/en-us/javascript/api/excel/excel.workbookprotection?view=office-js#protect-password-

Automatically move the screen to view the selection with an Excel add-in

I want to make a function to select a range in a workbook and visualise that range on the screen. My test shows that select() does select a range, whereas it does not always adapt automatically the screen to show the selection.
For example, I try to select and show Z10:Z10 under Excel for Windows by the following code. But after the selection, the screen does not move:
Office.initialize = function(reason) {
$(document).ready(function() {
app.initialize();
$('#testSelect').click(function() { select("Z10:Z10", "Sheet1") });
});
};
function select (rangeAddress, sheetName) {
Excel.run(function (ctx) {
var range = ctx.workbook.worksheets.getItem(sheetName).getRange(rangeAddress);
range.select();
return ctx.sync();
});
}
Could anyone help?
This appears to be a bug (or regression) in the APIs. The team is looking into it right now. In terms of a workaround, what Michael Saunders suggested above is probably your best short-term bet.
Update: This is indeed a bug (or regression) in the Excel desktop client. We have fixed it today, so for Office 365 / Click-to-Run users, it should be available with the next update (i.e., within a couple months).
~ Michael Zlatkovsky, Developer on Office Extensibility Team, MSFT
One option here in the callback after your code completes is to bind to the range and then navigate to it:
Office.context.document.bindings.addFromSelectionAsync(Office.BindingType.Matrix, {id: "myBinding"}, function(asyncResult){
Office.context.goToByIdAsync("myBinding", Office.GoToType.Binding, function(asyncResult){});
});
-Michael Saunders, PM for Office add-ins

Google Doc referencing another sheet

After speaking to Google Enterprise Support they suggested I create a post on Stackoverflow.
I have a Google Doc sheet with a list of stores (sheet A) and I'm trying to reference another sheet (sheet B) to VOID specific stores.
What I'm going to accomplish is if a store name on the void sheet is entered into sheet A it will automatically convert the store name to VOID.
Google support believes an IF statement would be the beginning to the solution, they weren't able to help beyond this.
For anyone's time that comes up with a solution, I'd be happy to buy you a couple Starbucks coffees. Your support means a lot.
make it simple using Google Scripts. (Tutorial)
To edit scripts do: Tools -> Script Editor
and in the current add this function
EDIT:
Well, you need to make a trigger. In this case will be when the current sheet is edited
Here is the javascript
function onEdit(event) {
// get actual spreadsheet
var actual = event.source.getActiveSheet();
// Returns the active cell
var cellSheet1 = actual.getActiveCell();
// get actual range
var range = event.source.getActiveRange();
// get active spreadsheet
var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
// get sheets
var sheet_two = activeSpreadsheet.getSheetByName("Sheet2");
range.copyValuesToRange(sheet_two, range.getColumn(), range.getColumn(), range.getRow(), range.getRow());
// get cell from sheet2
var cell = sheet_two.getRange(range.getValue());
cell.setValue(cellSheet1.getValue());
// display log
Logger.log(cellSheet1.getValue());
}
if you want to test it you can check my spreadsheet, there you can check that all data thats is inserted in sheet1 will be copied to sheet2

How to get the CodeName for Worksheet in Excel using VSTO

I did like this:
if (Excel._Application.ActiveWorkbook != null)
{
List<WorksheetKeyValue> sheets = new List<WorksheetKeyValue>();
foreach (object ws in ExcelApp.ActiveWorkbook.Worksheets)
{
string strCodeName = ws.CodeName
}
}
but strCodeName is an empty string when it supposed to be Sheet1, Sheet2, ..., SheetN like in VBA.
Thanks
In your condition, you can use Worksheet.CustomProperties as alternative to hold unique property of the sheet.
Worksheet ws = **current_sheet** as Worksheet;
ws.CustomProperties.Add("SheetID", **some_value**);
So, later on you can access them as
foreach (Excel.CustomProperty prop in ws.CustomProperties)
{
if (prop.Name == "SheetID")
{
// access as prop.Value and prop.Name
}
}
Hope this helps.
In VSTO, the CodeName property is an infra-structure property that you should not be using from your code.
From MSDN:
This property supports the Visual
Studio Tools for Office infrastructure
and is not intended to be used
directly from your code.
Tell us what you are trying to accomplish, maybe there is an alternative way to do what you want.
Also, I noted from your code that you are using an Excel Addin. You can try to check if the CodeName property returns what you expect if you use an Excel Document Customization instead of an Excel Addin.
Update:
In order for you to uniquely tag a worksheet you could use a GUID and set it as a custom property of the worksheet using Worksheet.CustomProperties.

Resources