I am trying to create a new sheet in my Excel file, but keep getting an "OLE method failed" error. I had found another function that added sheets and I tried to use that method, but I still get the error. Here is the code I'm using:
if (numSheetsCreated >= 3) {
checkRes(oleGet(objExcel, cPropertyWorkbooks, objWorkbooks));
checkRes( oleMethod( objWorkbooks, cMethodAdd ) );
}
That is the extent of the method to create a sheet. I check numSheetsCreated for >= 3 because a default Excel file automatically gives you 3 sheets to start with, but I get the error on the oleMethod function call and I don't know what the problem is. I'm hoping someone can help me figure this out.
Chris Christopher Cote - Thu May 16 13:02:08 EDT 2019 |
Re: Trouble creating new worksheet in Excel file hm, probably the same problem as here? https://www.ibm.com/developerworks/community/forums/html/topic?id=e7749444-1edd-4592-ba22-f71c9588d0a6&permalinkReplyUuid=cec1bf68-04b5-461e-9e61-19260c381e9d, i.e. you have to add a sheet to the sheets, not to the workbooks |
Re: Trouble creating new worksheet in Excel file Mike.Scharnow - Thu May 16 14:53:46 EDT 2019 hm, probably the same problem as here? https://www.ibm.com/developerworks/community/forums/html/topic?id=e7749444-1edd-4592-ba22-f71c9588d0a6&permalinkReplyUuid=cec1bf68-04b5-461e-9e61-19260c381e9d, i.e. you have to add a sheet to the sheets, not to the workbooks Actually, this is different from the other post. So how would I add a sheet to the sheets collection? Would it be:
if (numSheetsCreated >= 3) {
checkRes(oleGet(objExcel, cPropertySheets, objSheets));
checkRes(oleMethod(objSheets, cMethodAdd));
}
or am I writing the add function wrong for sheets?
Chris |
Re: Trouble creating new worksheet in Excel file Christopher Cote - Thu May 16 15:27:12 EDT 2019 Actually, this is different from the other post. So how would I add a sheet to the sheets collection? Would it be:
if (numSheetsCreated >= 3) {
checkRes(oleGet(objExcel, cPropertySheets, objSheets));
checkRes(oleMethod(objSheets, cMethodAdd));
}
or am I writing the add function wrong for sheets?
Chris No, have a look again at the script at https://www.ibm.com/developerworks/community/forums/html/topic?id=e7749444-1edd-4592-ba22-f71c9588d0a6&permalinkReplyUuid=90fb57dd-eb50-495d-b1cf-9649a803b1b9 The chain is: Excel -> Workbooks -> Workbook -> Sheets -> Add -> getActiveSheet -> post data to the sheet The only differences to the script in that post are that you open an existing workbook and there, a new workbook is created.
Oh, by the way: I am not completely sure whether a workbook created by an OLE method also contains 3 Sheets from the beginning onwards, I saw newly created workbooks with only one sheet, but I might confuse the use case here. |
Re: Trouble creating new worksheet in Excel file Well, I've been able to create new sheets with my code. However, the new sheets appear before the third sheet instead of after, so when I go to rename the newly created sheets, I end up renaming one of the sheets many times and the new sheets stay named "Sheet#". Here's the code:
int numSheetsCreated = 0;
void processSheet() {
string sheetName;
if (numSheetsCreated >= 3) {
checkRes(oleGet(objExcel, "Sheets", objSheet));
checkRes(oleMethod(objSheet, "Add"));
}
changeSheet(numSheetsCreated + 1);
sheetName = "Module " (numSheetsCreated +1) "";
checkRes(olePut(objSheet, "Name", sheetName));
createColHeadings();
numSheetsCreated++;
}
void init() {
for (n=1; n<=10; n++) {
processSheet();
}
}
Notice the names of the sheets in the attached image. Between Module 2 and Module 10, the other sheets still have the default "Sheet#" names. This is because when I'm on the 3rd sheet, adding a sheet adds it in front of this sheet, then the last sheet gets renamed using the numSheetsCreated variable. I thought about having 2 separate functions for creating and renaming the sheets and starting the second loop back at 1, but if I end up needing, say 50 new sheets, this small part of the function could take a rather long time to run and this doesn't include the rest of the functionality I still need to perform for each module. So that option is probably off the table.
Chris Attachments CreateExcelSheets.PNG |
Re: Trouble creating new worksheet in Excel file Christopher Cote - Fri May 17 08:44:42 EDT 2019 Well, I've been able to create new sheets with my code. However, the new sheets appear before the third sheet instead of after, so when I go to rename the newly created sheets, I end up renaming one of the sheets many times and the new sheets stay named "Sheet#". Here's the code:
int numSheetsCreated = 0;
void processSheet() {
string sheetName;
if (numSheetsCreated >= 3) {
checkRes(oleGet(objExcel, "Sheets", objSheet));
checkRes(oleMethod(objSheet, "Add"));
}
changeSheet(numSheetsCreated + 1);
sheetName = "Module " (numSheetsCreated +1) "";
checkRes(olePut(objSheet, "Name", sheetName));
createColHeadings();
numSheetsCreated++;
}
void init() {
for (n=1; n<=10; n++) {
processSheet();
}
}
Notice the names of the sheets in the attached image. Between Module 2 and Module 10, the other sheets still have the default "Sheet#" names. This is because when I'm on the 3rd sheet, adding a sheet adds it in front of this sheet, then the last sheet gets renamed using the numSheetsCreated variable. I thought about having 2 separate functions for creating and renaming the sheets and starting the second loop back at 1, but if I end up needing, say 50 new sheets, this small part of the function could take a rather long time to run and this doesn't include the rest of the functionality I still need to perform for each module. So that option is probably off the table.
Chris I have not been able to run your code.and I don't understand it completely.
Assuming that your code begins with
#include <utils/ole.inc>
OleAutoObj objExcel = oleCreateAutoObject("Excel.Application")
OleAutoObj objSheet = null
// Make it visible
olePut(objExcel, "Visible", true)
init()
and that your functions changeSheet and createColHeadings don't do anything at the moment. Then: in the first run of init(): objSheet is null -> there is nothing that shall get a name. So, I get an error null OleAutoObj parameter was passed into argument position 1
If I start your script with int numSheetsCreated = 4, then I get an error "An OLE method failed" in the line "oleGet(objExcel, "Sheets", objSheet). Which sounds logical as like posted above, the sheets belong to a workbook, not to the Excel object.
So, I'm not really sure how your script works and produces this result, some parts seem to be missing. With the following script, gathered from Mathias' script from the above mentioned post, I am able to create a new workbook which at the beginning contains only one empty sheet. I get this as the active sheet and am able to change it's name. Then in the next run, I create a new sheet, which is a method of "Sheets", which I got from the Active Workbook.
#include <utils/ole.inc>
void oleCheck (string s) {
if (!null s) {
print "An Error occurred: " s
halt;
}
}
OleAutoObj objExcel = oleCreateAutoObject("Excel.Application")
OleAutoObj objSheet = null
// Make it visible
olePut(objExcel, "Visible", true)
// get Application.Workbooks
OleAutoObj objWorkbookCollection= null;
oleCheck oleGet ( objExcel, "Workbooks", objWorkbookCollection)
// Add a workbook --> Application.Workbooks.add ()
oleCheck oleMethod(objWorkbookCollection, "Add")
// Get a handle to the newly added workbook --> Application.ActiveWorkbook
OleAutoObj objWorkbook = null
oleCheck oleGet (objExcel, "ActiveWorkbook", objWorkbook)
// Get a handle to the Sheets collection --> ActiveWorkbook.Sheets
OleAutoObj objSheetsCollection = null
oleCheck oleGet (objExcel, "Sheets", objSheetsCollection )
void processSheet(int n) {
print n"..1\n"
string sheetName;
if (n>1) {
print n"..2\n"
// Add a sheet ... ActiveWorkbook.Sheets.Add
oleCheck oleMethod(objSheetsCollection , "Add")
}
print n"..3\n"
// Get a handle to the sheet ...
OleAutoObj objSheet = null
oleCheck oleGet (objWorkbook, "ActiveSheet", objSheet)
print n"..4\n"
sheetName = "Module " (n) "";
print n"..5\n"
checkRes(olePut(objSheet, "Name", sheetName));
// changeSheet(objSheet);
// createColHeadings(objSheet);
}
void init() {
for (n=1; n<=10; n++) {
processSheet(n);
}
}
init()
And yes, with this code, the new sheets are created before the current sheet. This is in accordance with https://docs.microsoft.com/en-us/office/vba/api/excel.sheets.add?f1url=https://msdn.microsoft.com/query/dev11.query?appId=Dev11IDEF1&l=de-DE&k=k(vbaxl10.chm152073);k(TargetFrameworkMoniker-Office.Version=v16)&rd=true As stated there, "If Before and After are both omitted, the new sheet is inserted before the active sheet". So, you need parameters for the "Add" function. The "After" - Parameter needs the predecessor sheet. So, I put the last activeSheet into a temporary variable "latestSheet" and fill it before the next loop starts.
The script then looks like this (new lines denoted with //*)
#include <utils/ole.inc>
void oleCheck (string s) {
if (!null s) {
print "An Error occurred: " s
halt;
}
}
OleAutoObj objExcel = oleCreateAutoObject("Excel.Application")
OleAutoObj objSheet = null
// Make it visible
olePut(objExcel, "Visible", true)
// get Application.Workbooks
OleAutoObj objWorkbookCollection= null;
oleCheck oleGet ( objExcel, "Workbooks", objWorkbookCollection)
// Add a workbook --> Application.Workbooks.add ()
oleCheck oleMethod(objWorkbookCollection, "Add")
// Get a handle to the newly added workbook --> Application.ActiveWorkbook
OleAutoObj objWorkbook = null
oleCheck oleGet (objExcel, "ActiveWorkbook", objWorkbook)
// Get a handle to the Sheets collection --> ActiveWorkbook.Sheets
OleAutoObj objSheetsCollection = null
oleCheck oleGet (objExcel, "Sheets", objSheetsCollection )
OleAutoArgs autoArgs = create //*
OleAutoObj latestSheet = null //*
void processSheet(int n) {
print n"..1\n"
string sheetName;
if (n>1) {
print n"..2\n"
// Add a sheet ... ActiveWorkbook.Sheets.Add (After:=latestSheet) //*
clear(autoArgs) //*
put (autoArgs,"After", latestSheet) //*
oleCheck oleMethod(objSheetsCollection , "Add", autoArgs) //*
}
print n"..3\n"
// Get a handle to the sheet ...
OleAutoObj objSheet = null
oleCheck oleGet (objWorkbook, "ActiveSheet", objSheet)
latestSheet = objSheet //*
print n"..4\n"
sheetName = "Module " (n) "";
print n"..5\n"
checkRes(olePut(objSheet, "Name", sheetName));
// changeSheet(objSheet);
// createColHeadings(objSheet);
}
void init() {
for (n=1; n<=10; n++) {
processSheet(n);
}
}
init()
Hope this helps,
|