I have created an Access Custom Ribbon, with buttons to ‘Print’, ‘Save As PDF’ and ‘Close Print Preview’.
<group id="ReportingToolbar" label="Reports Toolbar">
<button idMso="FilePrintQuick" label="Print All" enabled="true" size="large" supertip="Print All"/>
<button idMso="FileSaveAsPdfOrXps" label="Print PDF" enabled="true" size="large" supertip="PDF This Document"/>
<button idMso="PrintPreviewClose" label="Close Report" enabled="true" size="large" supertip=" Close Report"/>
</group>
While the ‘Save As PDF’ works, it’s a bit clunky, having to choose a location to save the PDF each time.
I have written a Function to try to do this. It works perfectly when run from a Form, as I can supply the Report Name, the File Location and any Criteria/Where Clause, but I cannot get it to work through a custom ribbon.
Public Function OpenReportAsPDF(reportName, fileName, Optional criteria)
Dim File_Location As String
File_Location = PMG_Location & "\Temp_Files\" & fileName & ".pdf"
DoCmd.OpenReport reportName, acViewPreview, , criteria, acHidden
DoCmd.OutputTo acOutputReport, reportName, acFormatPDF, File_Location
DoCmd.close acReport, reportName, acSaveNo
Application.FollowHyperlink fileName
End Function
When I try to call this Function from the Ribbon using an ‘onAction’ argument, I don’t know how to supply the ‘reportName’ that is currently being Previewed, or a ‘filename’ or any ‘criteria’ so the Function errors with ‘Argument not optional’
The built in idMso="FileSaveAsPdfOrXps" ribbon HTML somehow knows what Report is currently being Previewed, but I don’t know how to programmatically supply the File Location and to open the PDF after it has been saved.
What I am looking for is a PDF button on my custom ribbon, to save the currently Previewed report and open it in the default PDF application.
I hope you can help.
Many thanks
Mark
Related
The Excel VBA code below opens a Selenium browser and navigates to the url in Sheet4!B2 (http://google.com).
Instead of the url, I'm replacing Sheet4!B2 with html code.
How do I inject html code into Selenium instead of navigating to the url?
All of the sources I happened to stumble upon point to running a local html file with code webdriver.get("file:///D:/folder/abcd.html");. This is very inconvenient since one can simply run the html code within Excel. Does Selenium allow you to do this?
Public Sub NavigateToURL1()
driver.Get [Sheet4!B2]
End Sub
You can achieve your stated aim with the following, which opens an empty browser window and render the HTML there.
Code:
Option Explicit
Public Sub GetHTMLfromCell()
Dim html As String
html = ThisWorkbook.Worksheets("Sheet4").Range("B2").Value2
Const WRITETOPAGE As String = _
"var txt=arguments[0];" & _
"setTimeout(function(){" & _
" document.open();" & _
" document.write(txt);" & _
" document.close();" & _
"}, 0);"
Dim d As New ChromeDriver
With d
.Get "about:blank"
.ExecuteScript WRITETOPAGE, html
Debug.Print .FindElementByTag("p").Text
.Quit
End With
End Sub
Credit to #FlorentB for this method.
Sample HTML in B2
<!DOCTYPE html>
<html>
<body>
<h1>My First Heading</h1>
<p>My first paragraph.</p>
</body>
</html>
Output:
References:
put a string with html/Javascript into selenium webdriver
Modify innerHTML using selenium
I am trying to use click a button through vba but it tells me that the "Object doesn't support this property or method".
My VBA code right now is:
IE.document.getElementByType("button").getelementByClass("qm_historyTab_GoButton").Click
The HTML for the button is:
<button class="qm_historyTab_GoButton" type="submit" style="font:normal 11px tahoma,arial,helvetica,sans serif;">
<span class="qm_historyTab_GoButtonText">GO</span>
</button>
Try this:
IE.document.getElementsByTagName("button") _
.getelementsByClassName("qm_historyTab_GoButton")(0).Click
Both of the getXXX methods return a collection of items (even if there's only one match in the document) so to address a single item from the last one in order to click it you need to add the (0)
EDIT: if the aim is to submit the form then this will also work
IE.document.getElementById("qm_historyForm_7871").submit
or as there's only one button with that classname:
IE.document.getElementsByClassName("qm_historyTab_GoButton")(0).Click
Ok so I found the solution in this specific instance. The button is a submit type and sends a message using HTMLInputElement.
What I needed to do was add "Microsoft HTML Object Library" to my references and utilize those features.
I had to create the variable that would send the response:
Dim htmlInput As MSHTML.HTMLInputElement
I couldn't figure out how to refer to this specific element individually so I grabbed everything with it's class name.
For Each htmlInput In IE.document.getElementsByClassName("qm_historyTab_GoButton")
If Trim(htmlInput.Type) = "submit" Then
htmlInput.Click
Exit For
End If
Next htmlInput
Then I had the program cycle through each item in the series and send a submit response. Since this was the only one with the class name, I got lucky.
So anyways, that's how I solved the problem.
Recently I created a custom ribbon for my access 2013 database. In my old access 2000 database I could always see the custom toolbars even if I opened the database with shift (designer mode - so I can see the tables, etc.).
In access 2013 however, I cant see my custom created ribbon when I open it with shift enter (I can only see the file, create, external data and help tools in the ribbon), is it possible to see the custom ribbon in designer mode (shift open)?
Here some additional information:
The ribbon is build in XML:
<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="OnMainRibbonLoad" >
<ribbon startFromScratch="true">
<tabs>
<tab id="tabBogus" label="Bogus" visible="false">
<group id="oPrint" label="Print- en pagina instellingen" >
<button idMso="PrintDialogAccess" size="large" label="Afdrukken" imageMso="PrintDialogAccess" getEnabled="MyEnabled" />
<button idMso="PageSetupDialog" size="large" label="Pagina instellingen" getEnabled="MyEnabled" />
<control idMso="FilePrintPreview" label="Print Preview" getEnabled="MyEnabled"/>
<button id="PrintKies" label="Standaard printer" screentip="Standaard printer" supertip="Stel de standaard printer in." imageMso="FilePrintQuick" onAction="ribbonOpenForm" getEnabled="MyEnabled" tag="PrinterKiezen"/>
</group>
</tab>
The code to load the ribbon is as follows:
Private m_ribbon As IRibbonUI
Private Declare Function apiGetUserName Lib "advapi32.dll" Alias _
"GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long
Sub OnMainRibbonLoad(OPSRibbon As IRibbonUI)
'handles the OnLoad callback of the customUI element
'and saves the IRibbonUI object reference to m_ribbon
Set m_ribbon = OPSRibbon
end sub
Public Property Get MainRibbon() As IRibbonUI
'global property that re-exposes the ribbon system-wide
'so consumers can call the IRibbonUI.Invalidate method as required
Set MainRibbon = m_ribbon
End Property
Private Sub Form_Current()
'consumes the global object reference to the ribbon
'calls its invalidate method
'and while rebuilding the ribbon your ToolEnabled() method will be called
'to enable, or not, your control
MainRibbon.Invalidate
End Sub
The custom ribbon is also set in the access 2013 options:
Current database --> Ribbon options -->Name Ribbon --> my ribbon
Any clue how I can load the custom ribbon in designer mode as well? With a button or something perhaps?
I would recommend avoid using Shift key for opening application in debug mode. Set something like “Debug” flag in the application, with this flag load debug version of custom ribbon (with startFromScratch="false") and bypass, for instance, logon screen. For release change ribbon to production version.
The other way – use LoadCustomUI method on form or in macro for loading your menu after starting the application with Shift key
On this web page: https://www.youtube.com/upload_defaults
I would like to call a function and then click the "Save" button in the upper right corner.
There is no ID or Name. How can I do this?
You can use the distinct CSS class of the button: account-save-button
In VB.NET, use HtmlDocument.GetElementsByTagName like this:
Private Sub ClickSaveButton()
If (WebBrowser1.Document IsNot Nothing) Then
Dim Elems As HtmlElementCollection
Dim WebOC as WebBrowser = WebBrowser1
Elems = WebOC.Document.GetElementsByTagName("BUTTON")
For Each elem As HtmlElement In Elems
Dim CssClass As String = elem.GetAttribute("classname")
If ((CssClass IsNot Nothing) And (CssClass.Length <> 0)) Then
If CssClass.ToLower().Contains("account-save-button") Then
elem.InvokeMember("click");
Exit For
End If
End If
Next
End If
End Sub
To verify it with just a web browser, try this from your browser's developer console; it works because youtube uses jQuery:
$(".account-save-button").click();
Or pure javascript: document.getElementsByClassName('account-save-button')[0].click();
For reference, here is the button's markup:
<button class="yt-uix-button yt-uix-button-size-default yt-uix-button-primary account-save-button account-action-button" type="submit" onclick=";return true;"><span class="yt-uix-button-content">Save</span></button>
Other thoughts:
This is basically screen scraping, which can lead to brittle applications when the page changes, etc.
Google may already have a web service API for what you are trying to accomplish.. but that's a good question:
What exactly are you trying to accomplish? What is the context? We may be able to suggest a better alternate solution.
Update:
I checked the Youtube API Reference, but I don't see anything for setting preferences for upload defaults.
I'm trying to do something I thought would be very simple - dynamically add some options in a select tag using ASP.NET.
I've written my code as:
<select id='cmbDuration'>
<% Dim periods As Generic.List(Of Models.Duration) = DBSupport.getDurations
For Each d As Models.Duration In periods
Response.Write("<option value='" & d.id & "'>" & d.name & "</option>")
Next
%>
</select>
All is well and the data returned by my db layer appear in my select tag.
Later on, I remembered to add a runat = "Server" tag, to process my data in my code-behind post. But, after adding that, no options are displayed. Checking the resulting source code, I see no options added to it as well.
What is the problem here? Why no options are shown when runat = "Server" is added?
Why are you talking about processing data in your code-behind post, but writing in-line code to generate list items? You should be binding your dropdown list in the code-behind:
ASP.NET
<asp:DropDown ID="cmbDuration" DataTextField="Name" DataValueField="ID" runat="server" />
CODE-BEHIND (in Page_Load)
If Not Page.IsPostBack Then
Dim periods As Generic.List(Of Models.Duration) = DBSupport.getDurations
cmbDuration.DataSource = periods
cmbDuration.DataBind()
End If
So, the way I understand this, is that adding the runat="Server"
attribute will result in my control being available for subsequent
process only in code-behind
No, adding runat="server" tells visual studio and the compiler that this control will be represented as a server control. It add's a server control into your .designer.cs file:
/// <summary>
/// Image3 control.
/// </summary>
/// <remarks>
/// Auto-generated field.
/// To modify move field declaration from designer file to code-behind file.
/// </remarks>
protected global::System.Web.UI.WebControls.Image Image3;
this process happens at design time.
Your code (everything inside the <%%>) happens at runtime. So your trying to build dynamic HTML using your code block. So the designer has no idea what your going to add, how many controls are your adding? How do I represent this? So it can't build the server side control code. So it doesn't. It also causes the runtime code to be unable to process the ViewState. Again it doesn't know what your controls are supposed to represent.
So you can't simply:
<select id='cmbDuration' runat='server'>
<% Dim periods As Generic.List(Of Models.Duration) = DBSupport.getDurations
For Each d As Models.Duration In periods
Response.Write("<option value='" & d.id & "' runat='server'>" & d.name & "</option>")
Next
%>
</select>
This is simply invalid ASP.Net syntax. You can't write to the code behind at runtime in this manner. Before your for-loop is executed .Net has already built up what code behind blocks it needs, so you can't add to this.
I'm not going to repeat what #Scott has already answered but this is what you need to do.
The problem is you are writing to ASPNET's "Response Stream" by using the function Response.Write(), which will cause the output'd option tags to appear at the very very top of the page where the Response Stream is printed. This will appear even above the HTML declaration tag. (Examine your HTML source code to see) If you wish to write output directly to the ASPX page, try this:
<select id='cmbDuration'>
<%For x As Integer = 0 To 5%>
<option><%=x%></option>
<%Next%>
</select>
If this helps, or not, please let me know!