Images in the office ribbon can be large (32x32) or small (16x16). If they are specified as large, but the window is too narrow to fit them, then they are automatically made small. By default, these are just a condensed version of the larger image.
There was an office design document (since disappeared) that suggested that one should properly design the small icons, and that they should not just be small versions of the big ones because condensing to 16x16 does not always work very well. Very sensible.
But does one actually do it in the XML? Elements like Button only seem to have one image attribute. I would expect two, largeImage and smallImage (say).
Is this something that really needs horrible call backs? In which case, how does one catch the event that the ribbon has decided to resize the image? (Ribbon call backs are a mess with VBA for several reasons.)
The Ribbon XML does not have an option to specify large and small icons as part of its defintion. If you use the image attribute then you can provide only one picture.
There's also no way to catch whether/when Office reduces the size of the Ribbon. You'd have to do some research, checking which window width triggers the resize, then you could use the WindowResize event of the Application object to invalidate the control(s), changing the picture (and possibly the control size).
In order to provide more than one icon you'd need to use the callback attribute getImage to tell the Ribbon which picture to use. This isn't as simple as passing the string value of a file stored in the Office document as the callback function expects an IPictureDisp object; the image would need to be stored outside the Office document, as a file.
The intricacies of using getImage are described in Customizing the 2007 Office Fluent Ribbon for Developers (Part 1 of 3), near the end of the article, but the code provided there is for the .NET Framework.
It's actually a bit easier to code using VBA since the stdOle library that provides IPictureDisp is an office library. You need to set a reference to the library - in the VBA Editor's Tools/References it's labelled as OLE Automation. Note that this does not work with the graphic png file format - the library is a bit old...
Public Sub GetIconImage(control As IRibbonControl, ByRef image)
Dim sPicPath As String
Dim stdPic As StdPicture
sPicPath = "C:\Users\[userName]\Pictures\test.jpg" 'Schweiz.png"
Set stdPic = stdole.StdFunctions.LoadPicture(sPicPath)
Set image = stdPic
End Sub
Related
The goal is to add the standard Solver button to a custom ribbon.
Background: I have code that creates a Solver model automatically using custom ribbon buttons. However, before actually running Solver, I would like the user to verify, and modify as necessary, the automatically-generated Solver model - by showing the Solver Parameters dialog box. For the user's convenience, I want to put the standard Solver button on my custom ribbon.
Problems were:
Solver does not have an official Microsoft msoImage or onAction item. So, I created my own button that called SolverOkDialog(). BUT,...
SolverOkDialog does not display the Solver Parameters dialog box (at least I couldn't get it to do so).
Solution:
Big picture: Grab the icon and link from Solver.xlam.
Copy C:\Program Files (x86)\Microsoft Office\Office15\Library\SOLVER\SOLVER.XLAM to a new file, Solver.zip.
Copy ….zip\customui\images\solver_icon.png to someplace convenient.
Using your favorite ribbon xml editor(1) assign solver_icon to RibbonX14.
Insert the following code to your custom ribbon:
<button id="btnSolver"
getLabel="solver.xlam!GetSolverLabel"
image="solver_icon"
onAction="solver.xlam!MainEx"
screentip="Solver"
supertip="What-if analysis tool that finds the optimal value of a target cell by changing values in cells used to calculate the target cell."/>
I hope this helps someone.
If I am missing something, please let me know.
(1) I use Leaf Creations Office Ribbon Editor because it is simple, functions well, and it is Creative Commons compliant.
I am running Excel 2016, which may be relevant if the below is a compatibility issue...
In short, I am trying to display a PDF, embedded in a UserForm in Excel.
I have a UserForm, say UserForm1.
I have enabled the following extra references:
Microsoft Visual Basic for Applications Extensibility 5.3
Adobe Acrobat Browser Control Type Library 1.0
This allows me to add the Adobe PDF Reader as an "Additional Control"
The control appears as a hatched box icon (bottom left), which I'm not sure it's meant to. Then if I try to add one of these objects to UserForm1 (both programmatically and in design view) it gives me an error
Element not found
For reference, the relevant lines of VBA I was using were:
Dim PDFviewer As AcroPDF
Set PDFviewer = PDForm.Frame1.Controls.Add("AcroPDF.PDF.1")
Which I took from this Adobe forums thread: https://forums.adobe.com/thread/1065554
Resources online suggest it might be that the AcroPDF control is no longer supported. If so, is there another way to achieve what I want?
As an alternative to using the AcroPDF, try using the WebBrowser Object.
It requires including the additional control
Microsoft Web Browser
Add a WeBrowser on the UserForm named WebBrowser1
Private Sub UserForm_Click()
Me.WebBrowser1.Navigate "about:blank"
Me.WebBrowser1.Document.write "<HTML><Body><embed src=""C:\temp\SO_Answers\test.pdf"" width=""100%"" height=""100%"" /></Body></HTML>"
End Sub
You can just .Navigate to the PDF directly, but, to quote my comment:
"It's safer to use the html part, depending on the machine settings, sometimes direct navigation will initiate download instead of display."
I have a requirement, where I search an excel. Since I am looping through all the rows and columns ( many rows and columns), its taking time. I want to display a message box while the search operation is going on.
Is it possible to do in VBA?
Thanks,
Yogesh
doevents interrupts the current thread and allows the user environment to be updated.
One of the eternal issues with VBA is its limitation of threads. VBA was conceived as a single-threaded model. Ever since, it remained so. Building a macro with multithread in native VBA is impossible.
Few workarounds are to build DLLs with COM interface and summon them in VBA or create worker scripts in VBS and use them from VBA.
This limitation of single thread widely annoys developers when it comes to display progress bar in excel. There is no API to communicate with the inbuilt progress bar of the Excel.
If you are looking to visually notify the user about some work that is under progress and they need to wait, all you are left with is either statusbar text or wait cursor. Another approach and bit intricate, because of their modal and non-modal styles, is to use UserForms. One more method, but very clumsy, unstable and non-native, is to use Internet Explorer object and update its HTML.
vba code :http://ashuvba.blogspot.in/2014/10/ajax-style-progress-display-in-vba.html
VBA is single-threaded, so the boring answer is "nope, can't be done".
Also, displaying a messagebox would block your only thread, so using one should be out of the question.
You have several alternatives.
Report progress in the host application's status bar. This can make your long-running task run even longer though, because now on top of the actual work, you need to refresh a UI element - DoEvents can help a bit here.
Report progress in a custom userform. This can be tricky, because you probably don't want that form to actually own the code/logic that performs whatever it is that your long-running task does; you'll need to encapsulate that logic in a class/object, and let the form call into that object - the object exposes some Public Event UpdateProgress, and then the form needs to declare some Private WithEvents myLogic As MyObject to handle that event.
Wrap a .NET BackgroundWorker into a COM-visible library, and let .NET create the background thread for you.
This is how I mimic progressbar when the code runs long:
add separate hidden sheet like that:
(white background, range B2:G2 merged and formatted as %, all other rows/columns hidden)
apply conditional formatting to B2: Data bars - Lowest value: 0, Highest value 1, choose progressbar background color
when the code starts running, unhide and activate it, on progress change B2 value (0->0%, 1->100%), and call DoEvents to invalidate
hide this sheet and activate the main sheet on completion
I just found out there is a limit for the number of controls that a mfc dialog can hold, I have near 653 controls, the dialog holds just 332 of them, I searched for a solution, some suggested property sheets and property pages, but I dont's want to distribute these 653 controls in some tabs! I want all of them in one tab, so, what else can I do except using tab control or property sheets? Is it possible at all?
This is the form
It appears that some kind of grid control is what you are after. It is a single control in a form of a table that contains many cells. Both table and cells can be customized. Code Project has a whole section dedicated to grid controls. Here are first few from that section, free of charge:
http://www.codeproject.com/Articles/3176/The-ALXGrid-Control-Library
http://www.codeproject.com/Articles/8/MFC-Grid-control-2-27
http://www.codeproject.com/Articles/2879/Virtual-Grid-Control-1-04
653 controls? Seriously? No matter if the resource editor can handle it, such programming style is simply forbidden! Also, it's a waste of window handles. You should consider using a list/tree instead.
Create your controls programmatically! Inherit CWnd and create your own control. Then add an array of your controls and dynamically create them in OnCreate.
Our web application has some event code to "format" any text with pasted into a field so that any HTML styles do not break our data.
What would be a good way to pre-load the browser clipboard so that I can test pasting into the input field?
Is there any way to do it programmatic-ally or would I have the test script visit "a source page" and copy text before moving onto our application?
Any ideas or code snippets would be welcome.
Working with the clipboard will depend on your platform. E.g. on OS X, you can use pbcopy and Command-V:
open('|pbcopy', 'w') { |io| io << 'some text' }
browser.text_field(:name => 'q').send_keys([:command, 'v'])
I know there are equivalents on Linux (xclip?). Not sure about Windows.
I would consider using the .value= method to set the value. If it's been implemented the same as in watir, then it causes no events to be fired and sets the value directly, and then follow that up by sending an appropriate event (depending on what if any events are being monitored) such as onKeypress. I tried to figure out from the Watir-webdriver rdoc for textfield, if this distinction between .set and .value= has been maintained, but the way the doc describes them (at least there) makes them seem interchangable.. (Jarib can you clarify???)
Potentially you might need to first fire something like onFocus depending on the controls you are using. For example, as described in this SO case Setting a text field that has a JQuery mask on it for a jquery mask, they had to end up firing an unmask event to be able to even set the field.
This is a good case for utilizing the techniques described here How to find out which JavaScript events fired? and in the SO item linked in the comments for that question, to figure out just what events are fired when you manually paste something into a field. (note I would slueth it with both using the mouse, but also using something like tab to move between fields and set the focus, events common to those two methods are the ones most likely to be implemented by the controls.
I presume you have some kind of client side javascript that needs to check what was pasted into the field, and thus the reason for this test. If you are using standard HTML fields, with no javascript stuff, then I would consider this particular test case to be effectively the same as 'testing the browser' since supporting cut and paste in input fields is a standard browser function. In that case, you are sort of 'off the reservation' and I'd not bother with such a test case.