Get ID of excel worksheet in focus using OLE - c++

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" );

Related

Delete All records in a Siebel List View

I need to Delete All the records in a list applet by a button clicked method. In order to achieve this, I have added a button to the list applet with "DeleteAllRecords" method and added a script to BC PreInvokeMethod function as below. Once clicked on the button all the records will get deleted, but the applet won't get refreshed. How Can I achieve that?
try
{
if(MethodName == "DeleteAllRecords")
{
var EmpBO = TheApplication().GetBusObject("XXXX");
var EmpBC = EmpBO.GetBusComp("XXXX");
with(EmpBC)
{
SetViewMode(AllView);
ActivateField("EmployeeID");
ClearToQuery();
SetSearchExpr("[XXXX] <> ' '");
ExecuteQuery(ForwardOnly);
var Frecord = FirstRecord();
while(Frecord)
{
Frecord = DeleteRecord();
Frecord = FirstRecord();
}
}
//BC.InvokeMethod("RefreshBuscomp");
return (CancelOperation);
}
}
catch(e)
{
throw(e);
}
finally
{
EmpBO = null;
EmpBC = null;
}
return (ContinueOperation);
You could try a few things.
1: A simple null query in the end after all deletions are done. ClearToQuery() and ExecuteQuery();
2: There is a BC method for RefreshBusComp (check documentation) which can be used with InvokeMethod(). Does pretty much the same thing as 1. I see you already tried it and probably did not work.
3: There are Business services which can refresh applets , like FINS Teller UI navigation.
4: You could also try a null query in browserscript/javascript, put that in InvokeMethod, so that it runs after the BC escript. Genb has to be run to generate bscripts.
One of these should work .

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.

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

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;

Switch ribbon category for the user

I have a program written in C++ using MFC. It has a ribbon UI, Office style.
I would like to achieve the following - Suppose the user has highlighted category A of the ribbon, and clicks a button in that category, I would like my program to switch to category B and highlight it for him in response to that click.
This might sound strange, but I really have a use case where the user might not realize that he needs to switch categories, so I would like to do it for him automatically.
Can this be done?
Perhaps you're looking for CMFCRibbonBar::SetActiveCategory.
There is a similar question on CodeProject that includes a sample function for programmatically selecting a category by name. Reproduced below for information:
int CYourClassName::ActivateCategoryByName( CString strCategoryName)
{
// Grab Pointer to MainFrame
CMainFrame* pMainFrame = ( CMainFrame*) AfxGetMainWnd();
// Grab Pointer to RibbonBar
CMFCRibbonBar* pmrb = &pMainFrame->m_wndRibbonBar;
// Get Category Count
int nCategoryCount = pmrb->GetCategoryCount();
// Scan Category
for ( int nCategoryNdx = 0; nCategoryNdx < nCategoryCount; nCategoryNdx++)
{
// Grab Pointer to Category
CMFCRibbonCategory* pmrc = pmrb->GetCategory( nCategoryNdx);
// Get Category Name
CString strName = pmrc->GetName();
// Check for Requested Category
if ( strName == strCategoryName)
{
pmrb->ShowCategory( nCategoryNdx, TRUE);
pmrb->SetActiveCategory( pmrc, TRUE);
return nCategoryNdx;
}
}
return -1;
}

How do I add a ComboBox to a TreeView column?

In Gtkmm, I want to have a Gtk TreeView with a ListStore, and have one of the columns in the list be a ComboBoxText. But I can't seem to figure out how to do it.
What I currently have looks like:
class PlayerListColumns : public Gtk::TreeModelColumnRecord
{
public:
PlayerListColumns()
{ add(name); add(team);}
TreeModelColumn<string> name;
TreeModelColumn<ComboBoxText*> team;
}
Then when setting the TreeView (the player_list_view object)
PlayerListColumns *columns = new PlayerListColumns();
Glib::RefPtr<ListStore> refListStore = ListStore::create(*columns);
player_list_view->set_model(refListStore);
ComboBoxText *box = manage(new ComboBoxText());
box->append("Blah");
box->append("Blah");
box->append("Blah");
TreeModel::Row row = *(refListStore->append());
row[columns->name] = "My Name";
row[columns->team] = box;
The column "name" shows up just fine, but no ComboBox. I'm almost positive that simply having a pointer to a combo box as the column type is wrong, but i don't know how it's supposed to go. I do get GTK warning:
GLib-GObject-WARNING **: unable to set property text' of typegchararray' from value of type `GtkComboBoxText'
Which seems to indicate (from a small bit of Googling) that there isn't a default renderer for non-basic types. But I haven't been able to find any examples of how to set one up, if that were the problem. All the tutorials only show TreeViews with primitive data types.
Anyone know how to put a ComboBox into a TreeView?
Okay, I haven't gotten it working 100%, but this example class should get you on the right track:
http://svn.gnome.org/svn/gtkmm-documentation/trunk/examples/book/treeview/combo_renderer/
Basically you need to add a Gtk::TreeModelColumn<Glib::RefPtr<Gtk::ListStore> > to your columns class and a Gtk::TreeModelColumn<string> to hold the selected data.
Then, to make a column a combobox, you have to add:
//manually created column for the tree view
Gtk::TreeViewColumn* pCol = Gtk::manage(new Gtk::TreeViewColumn("Choose"));
//the combobox cell renderer
Gtk::CellRendererCombo* comboCell = Gtk::manage(new Gtk::CellRendererCombo);
//pack the cell renderer into the column
pCol->pack_start(*comboCell);
//append the column to the tree view
treeView->append_column(*pCol);
//this sets the properties of the combobox and cell
//my gtkmm seems to be set for Glibmm properties
#ifdef GLIBMM_PROPERTIES_ENABLED
pCol->add_attribute(comboCell->property_text(), columns->team);
//this is needed because you can't use the ComboBoxText shortcut
// you have to create a liststore and fill it with your strings separately
// from your main model
pCol->add_attribute(comboCell->property_model(), columns->teams);
comboCell->property_text_column() = 0;
comboCell->property_editable() = true;
#else
pCol->add_attribute(*comboCell, "text", columns->team);
pCol->add_attribute(*comboCell, "model", columns->teams);
comboCell->set_property(text_column:, 0);
comboCell->set_property("editable", true);
#endif
//connect a signal so you can set the selected option back into the model
//you can just have a column that is not added to the view if you want
comboCell->signal_edited()
.connect(sigc::mem_fun(*this,&ComboWindow::on_combo_choice_changed));
EDIT ABOVE
I think something along the lines of using a Gtk::CellRendererCombo* is the way to go in your PlayerListColumns
http://developer.gnome.org/gtkmm/stable/classGtk_1_1CellRendererCombo.html
(I haven't made a working test yet, but I got the idea from:
http://developer.gnome.org/gtkmm-tutorial/unstable/sec-treeview.html.en#treeview-cellrenderer-details)