Seems simple and probably a case of "It's monday" but I can't find the answer to this.. without having to record all the pagesetup variables in strings beforehand, is there a way to copy a worksheets .pageSetup property?
in a macro im running, I create a new page, paste some data, change a bunch of pagesetup settings, then print. I was hoping there was a way i could save the page setup before hand, and apply it again afterwards so my users don't have to worry about fixing settings ever.
I tried:
dim ws as worksheet
set ws = ActiveSheet.pageSetup
'settings change / print
ActiveSheet.pagesetup = ws.pagesetup
that doesnt work because ws.pagesetup is now linked to activesheet.pagesetup, so as soon as i change the active sheets settings, ws's settings get changed too.
I also tried set ws = sheets(1) because the new page is never the first page, but then with that one ActiveSheet.pagesetup = ws.pagesetup doesnt work either, it says object doesn't support this property or method
Is there a simple way? must I have 20 different string variables to hold all the current pagesetup variables?
Thanks
When I want to accomplish something like this I'll save all my formatting and pagesetup stuff to a hidden sheet. At the right time I'll have my code copy and paste everything where I need it. In this case it would probably be easiest to start by making a copy of the hidden sheet. Then dump in your data and work from there.
Rather than coping page setting from a master sheet to other sheets:
Create the master sheet
Establish the page settings for this single sheet
Make copies of the master
Populate the copies with data, formulas, etc.
In other words, anticipate your needs and setup the sheets in advance.
Related
I am attempting to copy different images to different worksheets of my Workbook using the following code below. I am changing the Target Worksheet Dynamically in a different sub, with a String Variable in the Global Declarations section. I can see the variable being passed to the sub and in fact it works the first pass through the code, but when I attempt to change the "TargetSheetIni" variable to a new sheet, it continues to use the first original sheet as it loops through.
Can you not change a target sheet after using the Set keyword? Should I refer to the sheet directly instead?
Sub Test1()
Dim TargetWS, SourceWS As Worksheet
Set TargetWS = Worksheets(TargetSheetIni)
Set SourceWS = Worksheets("Images")
DoEvents
SourceWS.Shapes(CurrentImageId).Copy
DoEvents
TargetWS.Paste Range(ColumnLetter2 & RwCnter)
DoEvents
End Sub
I think I may have figured it out. As far as I can tell the issue may be that I used the Copy Sheet Functionality in Excel when I originally created the target sheets. And even though I renamed the sheets both on the tab below and in the project editor... for some reason VBA kept targeting only the original sheet
I proved this by changing my code around to explicitly call the sheet I wanted to target like so:
ActiveWorkbook.Worksheets("Sheet2").Paste Range("I2")
And even doing that it would target sheet 1 for the paste command instead of the expected sheet 2. I deleted the three copy sheets and created a new one from scratch and re-executed code and now it targets sheet 2 as expected.
I found this article that sort of explains it I guess...
https://www.spreadsheetsmadeeasy.com/7-common-vba-mistakes-to-avoid/
Ok my last answer may have not been correct. It appears as though for some reason inserting an ws.activate caused my code to start workin.g
Very frustrating fix. as I have always heard to avoid using that.
I have created a dynamic workbook where i put and pull data to more sheets containing data from other sources. I have a "Temp" sheet where code updates som data, this sheet is hidden until the macro is run, to put and pull data, i make it visible and when finished i hide it again. This works (almost) perfect.
The problem occurs when i hide it, then my last Sheet i selected automatically? My code is totally without any .select or .active (Still learning) because it is important that code always return to the sheet from where the code is run as this changes name everyday.
I can't seem to find anything that solves my issue, hope somebody can help:
I tried the following, as you can see in the following code:
Sheets("Temp").Cells.ClearContents
Sheets("Temp").Visible = False
'Cleans filters
ActiveSheet.ShowAllData
Application.Goto Range("A4")
Application.ScreenUpdating = True
I want to always stay in my activesheet (example: ("16") which is the actual date, there will be one sheet for everyday etc. ("17"), ("18") and so on.)
You can use With to immediately reactivate the sheet, like so:
With ActiveSheet
OtherSheet.Visible = xlSheetVisible
.Activate 'Immediately reactivate the ActiveSheet
End With
(You may want to toggle Application.ScreenUpdating so that you do not see so much as a flicker of the other sheet)
However, why do you need to show the sheet to copy data from it? If you are not using Select (which you say you are already sorted on), then you should be able to do most things with a Hidden sheet, such as HiddenSheet.Range("A1:B3").Copy
(A "Very Hidden" sheet, on the other hand, has a couple of restrictions - for example, you cannot delete a Very Hidden sheet.)
I'm using this code to copy formulas from one workbook to another.
For Each r In templateWbk.Sheets("BSC").Cells.SpecialCells(xlCellTypeFormulas)
addressRange = r.Address
r.Copy instanceWbk.Sheets("BSC").Range(addressRange)
Next
Occationally I get a popup that says "The name "xxxxx" already exists. Click Yes to use that version of the name, or click No to rename the version of "xxxxx" you're moving or copying.
I don't want this popup to appear. I always want the exact content of the cells to be copied and nothing more, in other words I want to use the existing version of the name. This is the major thing I need help with.
The code is also rather slow as the sheets have many formulas. So if you can suggest a faster approach I would be thankful for that as well.
Could you simply set the value in one workbook to equal the value in the other? This would keep eliminate the "copy" method:
For Each r In templateWbk.Sheets("BSC").Cells.SpecialCells(xlCellTypeFormulas)
instanceWbk.Sheets("BSC").Range(r.Address).Formula _
= templateWbk.Sheets("BSC").Range(r.Address).Formula
Next
Also, you may try to change the DisplayAlerts property:
Application.DisplayAlerts = False
Untested for your scenario, but a good way to get rid of many popups.
I am using VBScript to make lots of calculations on different sheets on the same workbook. Now one concern is if somehow someone deleted any of the sheet, the script would then lead to massive data loss. Is there any way to protect it from users?
(Make sure you read the edit at the end of this answer)
I have similar workbooks I have made that use sheets like databases, so I understand your concern of protecting the information. If you are protecting the Workbook, it will prevent your macro from performing certain changes to the sheets/book. However, if you only want to protect the sheet contents, you can use the setting UserInterfaceOnly, which will allow your macro to run freely while still protecting the sheets from the users. You can detect if the sheets are protected when opened, and if not, protect them.
Sub test()
dim mySheet as worksheet
dim myPass as string
myPass = "password"
set mySheet = Excel.ActiveSheet
if mySheet.ProtectContents = False then
mySheet.Protect Password:=myPass, UserInterfaceOnly:=True
end if
'Enter your code here
mySheet.Unprotect Password:=myPass
End Sub
Furthermore, if you want to give the user the ability to unprotect the sheets after being warned, then you can use Custom UI Editor to remove the protect/unprotect sheets group from the review tab and then replace it with a customized button. I've done this in the past and it actually helped a lot with maintaining the sheets later. I've included a couple links on Custom UI Editor below.
Custom UI Editor Download
Custom UI Editor Tutorial - Change the Ribbon in Excel 2007 or
2010
EDIT:
At first glance I thought this question pertained to VBA (my bad). I believe the above code can still apply, just place the code within the tags and set the workbook and worksheet variables properly (not the way they are set above). If you don't already know how to set/reference your workbook/worksheetsheet objects, this forum post shows how. Albeit I don't normally work with VBscript, but the forum looks correct. Good luck!
i nw this was a few years ago, but i ran into it when searching for the answer, hopefully someone fins this helpfull.
First add a password to your workbook that way other users will only be able to open as read only.
http://www.k2e.com/tech-update/tips/728-tips-adding-a-password-to-make-an-excel-workbook-read-only
then to make as part of the vbscript when opening the excel file(s)
Set oExcel = CreateObject("Excel.Application")
Set oWorkbook = oExcel.Workbooks.Open(file.path,,,,"password","password",True,,True,True)
full list of switches can be found here:
http://msdn.microsoft.com/en-us/library/office/ff194819%28v=office.15%29.aspx
hope that helps, took me hours to figure this out.
I've got an Access 2007 database on which I have created around 15 SQL queries to process specific data, I have created a main frame navigation menu using menus in Access, I now need to extract all th queries to Excel using VBA code, I have managed to do this with the code below by creating a button and specifying this code to it.
Private Sub query1_Click()
DoCmd.TransferSpreadsheet acExport, _
acSpreadsheetTypeExcel9, "Total Users and Sessions", _
"C:\UsersandSessions.xls", , "Total Users & Sessions"
End Sub
Now my problem at the moment is that fine the query is exported to Excel, but it is done so without any formatting applied at all, I would like to add some formatting at least to the headers and maybe a title inside the spreadsheet, and one thing I dont really like is that all records are being started from the first cell. Also I would prefer that if I hit that button again in Access and the Excel spreadsheet has already exists with that query output then when clicked again it will write again to a the next available sheet.
Any suggestions or ideas a very welcome.
The short story, is you can't. You might be able to do some scripting on the Excel side to format the resulting file. If you want something pretty, you probably want to create a report.
You could, instead mount the excel sheet as a table, and then on a separated sheet in the excel file, reference the first sheet, and format the second sheet for viewing.
if you use DoCmd.TransferSpreadsheet and create an original and then edit it so that the formatting is correct, you can then run DoCmd.TransferSpreadsheet again and it will update the file with the values but keep the formatting.
However, if a human then changes the file by adding new tabs, or adding calculations, etc, then the DoCmd.TransferSpreadsheet will no longer work and will fail with an ugly error message. So what we do in our enviroment is DoCmd.TransferSpreadsheet to an original file with formatting, and follow that up in the VBA by copying the file to the users desktop, and then opening that copy so the user doesn't mess up the original source excel file.
This approach is a minimum code, clean, and easy to maintain solution. But it does require a extra "source" or original file to be hanging around. Works in Access 2007.
You also would like the results to end up on a new tab. Unfortunately, I think it will take some excel automation to do that. The VBA inside Acccess can call a function inside the VBA in Excel. That VBA could then copy the tabs as needed.
My idea would be a hybrid of Excel automation from Access and creating a template in Excel as well that would have a data table linked to your query.
To start create your data table in Excel. You can start three rows down and two columns to the right if you want or wherever. Go to your data tab and click access, find your db, choose your query you want to link to, choose table as the radio button but click properties next instead of ok, uncheck the enable background refresh, this part is critical ... under the definition tab in the connection string you will see a part that says Mode=Share Deny Write change that to Mode=Read, this will make sure that the query refreshes without errors from an MS Access VBA while the db is open and will keep your users from writing back to the db in case your query is a writeable query. Once you set that up you can adjust the table formatting however you choose from the table design tab and it will keep that formatting.
For the purposes of this we are going to assume you started the table in cell B4 ,and your named the worksheet CurrentDay, for purpose of the following VBA example be sure to replace that reference with your actual placement.
Next go back to Access and write your VBA first ensure that in your VBA window you have the reference to Microsoft Excel 12.0 Object Library is selected by going to Tools > References and selecting it from the alphabetical listing.
Create your sub as follows:
Sub query1_click()
Dim xl as Excel.Application
Dim wbk as Excel.Workbook
Dim wks as Excel.Worksheet
Dim RC as Integer
Dim CC as Integer
Set xl = New Excel.Application
Set wbk = xl.wbk.Open "X:\Filelocation\FileName.xlsx" 'name and path you saved the file you previously created
xl.Visible = True
'The above is not necessary but you may want to see your process work the first few times and it will be easier than going to task manager to end Excel if something fails.
RC = xl.Application.CountA(xl.wbk.Worksheets("CurrentDay").Range("B:B")) + 3 'This will count the rows of data in your table including your header so you can copy the data to another tab dynamically as the size of your table expands and shrinks we add 3 to it because we started at row 4 and we need the location of the last row of the record set.
CC = xl.Application.CountA(xl.wbk.Worksheets("CurrentDay").Range("4:4")) + 1 'This counts the header row and adds one space because we will use this as a location holder for our copy / paste function
Set wks = xl.wbk.Worksheets.Add
wks.Name = format(date(),"MM_dd_yy") 'this will name the tab with today's date... you can eliminate this step if you just want the sheets to be the generic Sheet1, Sheet2, etc.
With xl.wbk
.Worksheets("CurrentDay").Range(Cells(4,2),Cells(RC,CC)).Copy
.wks.PasteSpecial xlPasteValues 'This pastes the values so that the table links do not paste otherwise every tab would just refresh everyday.
.wks.PasteSpecial xlPasteFormats 'This gets your formatting.
.RefreshAll 'This will refresh your table
Wend
With xl
.Save
.Close False
.Quit
Wend
Set xl = Nothing
Set wbk = Nothing
Set wks = Nothing
End Sub
That should get you to have your data to not start on A1 of your sheets, save your old data each time, and automate the steps from access.