The setup
I have an Excel workbook stored on my hard drive.
The structure is such that on the first sheet I have a list of the names of the other sheets in the same workbook (...which can be created or deleted).
All the names on the list, on the first sheet, are supposed to be hyperlinks to the corresponding sheet in the workbook. So, by clicking the name on the first sheet you jump to the corresponding sheet.
When a new sheet is created a macro creates also the new name on the list on the first sheet and makes a hypelink of it. This works.
...BUT...
The links point to the stored version of the file, not to the open workbook! Clicking the links opens the stored file and not the one which is under work.
QUESTION: How to create a hyperlink that always points to the same open workbook and not to the stored copy of it?
Try this:
ActiveSheet.Hyperlinks.Add Anchor:=Selection, Address:="", SubAddress:= _
"Sheet3!", TextToDisplay:="Link to sheet #3"
Address is the URL and SubAddress is a localtion of the page (or a sheet or a range in excel workbooks).
You may try creating the hyperlink as a formula (via VBA, as you need).
I am using the parameters you posted, this may need a little adjustment.
Dim rngsrc as Range, rngtrgs as String
Set rngsrc = Worksheets("Summary").Cells(Cell.Row, 5)
Set rngtrg = "'" & sSheetName & "'!B5"
rngsrc.FormulaR1C1 = "=HYPERLINK(" & rngtrgs & "," & sSheetName & ")"
See
Official documentation
Example 1
Example 2
This (hopefully) answers your question. As a separate note, it still remains to be clarified why you see the behavior you see.
It seems that the problem comes from the following fact: My file is in a SharePoint folder. If I open it just for reading, the hyperlinks work fine. If I open the file for editing, a copy of the SharePoint file is placed on my hard disk, on a specified location. So, the path to the file is not the same as it would be if I open it read-only. Should I use hyperlink.follow to solve this?
So, this all comes down to the question: In VBA/Excel, can I create a hyperlink which always points to a location in the same opened file so that the hyperlink ignores the storage path of the corresponding file? Using empty string (or BLANK) doesn't help as the address parameter in hypelinks.add as Excel seems to automatically fill in the whole storage path.
I upgraded to Office 2013 and "PADAM": The problem vanished! It seems that there was a bug in Excel/VBA in this in the 2007 version.
Related
I currently use a spreadsheet where I need to manually hyperlink 4 separate files in each row which include important information for referencing (3 are PDFs and 1 is an excel spreadsheet). Each row is full of information for a specific order number, which is conveniently part of each file that I need to hyperlink. Each of the 4 types of documents I would like to hyperlink into my excel sheet are also all packed into 4 folders path1, path2, path3, and path4, and they have their own column in the spreadsheet. Each folder will only contain one file with the order number.
I tried to automate this in excel only, using these formulas in the 4 columns:
K2 =IF(ISBLANK(C2)," ",HYPERLINK("J:path1\"&C2&".pdf",C2))
L2 =IF(ISBLANK(C2)," ",HYPERLINK("J:path2\"&C2&".pdf",C2))
M2 =IF(ISBLANK(C2)," ",HYPERLINK("J:path3\"&C2&".xlsx",C2))
N2 =IF(ISBLANK(C2)," ",HYPERLINK("J:path4\"&C2&".pdf",C2))
The formula references cell C2 which is the order number, and it fills the path with that number, which works great for the files which are consistently named. It also leaves the cell blank if there is no order number, because it happens sometimes and I need the function to not freak out when there is nothing there. The problem comes when I run into the file names that have other things tacked on the end such as a date. My formula is incapable of hyperlinking a file unless I give it the exact path to begin with.
I am wondering if anyone knows if excel is even capable of finding a file in a folder when only given part of the file name.
If there is not a way to do this in excel, I was hoping there may be a way to do this with VBA. I did some searching and found the Application.FileSearch feature in VBA, but it says "Object doesn't support this action." when I try to call it. (Which from a simple google search that seems to be the error due to Application.FileSearch not existing in excel 2007, but I am running 2013, so I'm not sure why this is happening)
I have a very novice understanding of VBA, so I am trying to slowly learn on the side. If anyone could help me come up with a code that would allow me to reference a cell, and find files containing that name so that I could print that path to a different cell, I would greatly appreciate your help.
Something like this should work (or at least point you down a path to investigate).
Sub HyperlinkFiles()
Dim strFile As String
strFile = Dir$("J:\path1\*" & Sheet1.Range("C2") & "*.pdf")
If (Len(strFile) > 1) Then
Sheet1.Range("k2").Hyperlinks.Add Sheet1.Range("k2"), strFile
Else
'No file was found that match so do nothing
'However, you could link to the folder to make manually searching easier
'Sheet1.Range("k2").Hyperlinks.Add Sheet1.Range("k2"), "J:\Path1"
End If
strFile = Dir$("J:\path2\*" & Sheet1.Range("C2") & "*.pdf")
If (Len(strFile) > 1) Then
Sheet1.Range("L2").Hyperlinks.Add Sheet1.Range("L2"), strFile
Else
'No file was found that match so do nothing
End If
strFile = Dir$("J:\path3\*" & Sheet1.Range("C2") & "*.xlsx")
If (Len(strFile) > 1) Then
Sheet1.Range("M2").Hyperlinks.Add Sheet1.Range("M2"), strFile
Else
'No file was found that match so do nothing
End If
End Sub
The caveat with this code is when there are 2 or more files that match the search pattern. For example, suppose cell C2 contains Stack and you have 2 files named stackoverflow.pdf and stackexchange.pdf. Which "stack" file do you want?
I am almost completely new to using VBA and Macros on Excel 2010. I know little to nothing about macro coding, and I just started a day ago trying to pick it up.
I was asked to create a macro that copies ONLY the data from 12 workbooks and pastes it onto a blank workbook (they all have 1 sheet each, with the data on each workbook starting on cell A3 while stretching to column S (the amount of data on the sheets vary)).
NOTE: When I mean "ONLY the data," the cells that I want to be copied include the blank cells that are in between the first and last parts of the data.
1) When copying data from one workbook to another, do you HAVE to specify the cells that you would like to copy? Or is there a way to specify where the data ends on the sheet, and then copy all of that data? If so, then could someone show me how to do so? The reason for doing so is because the macro will be used weekly.
and 2) Could someone simply help me develop this macro? Help would be massively appreciated :)
Some Extra Notes:
- The Workbooks are named "Status by offering ID [1-12]
Thanks again!
Ripster has given one example of missing information from your specification.
Santosh recommends a pretty neat tool but my reading of your question is that your knowledge is not up to using a tool yet.
I deduce this is a work question and your boss has asked you to write this macro despite your knowledge of VBA being zero. This seems to be a growing problem: you can discover the answer to anything on the net so why bother with training people. Even if you produced a complete specification of your requirement, I doubt anyone will give you a complete solution. If they do provide a complete solution, it will not help with the next requirement. So I am going to break your problem down into the type of questions you can ask the net.
Each week you get 12 source workbooks and create a summary by consolidating data from the source workbooks. Do you overwrite the previous week's summary with the new summary or do you want to save all the summaries? It will not add much to the complexity to keep all the summaries but you need to decide what you want.
If you discard the previous summary, the macro can be in Summary.xlxm, say. If you save the summaries, the macro will need to be in its own workbook, Macro.xlsm say, and it will create a different summary workbook, SummaryYYWW.xlsm say, each week.
If you search for "Workbook Open" and "Workbook Create", you will find instructions on how a macro in one workbook can open other workbooks and create new workbooks.
Where are the source workbooks? Are they in the folder CurrentData which is overwritten each week? Are they in the folders Week1301, Week1302, Week1303 and so on? Are they in the folder NewData and the macro is to move them to folders Week1301, Week1302, Week1303 and so on after processing? All these are options but I suggest you start by moving the source and summary workbooks to/from a folder convenient for the macro.
Look up "ThisWorkbook" and "ActiveWorkbook". In brief: "ThisWorkbook" is the workbook containing the macro and "ActiveWorkbook" is the most recently opened workbook.
Look up workbook property "Path". ThisWorkbook.Path, for example, gives you the name of the folder containing ThisWorkbook. Look up workbook property "Name".
If the source workbooks always have the same names, you could hard code the names into the macro. I do not recommend this. Look up the function "Dir".
I hope the above has given you a start on breaking your total problem down into its components.
There are many different VBA tutorials available on the web. Try a few and pick one you like.
"Debug.Print xxx" outputs the value of xxx to the Immediate Window. This can be very helpful as you start. Try this as your first macro:
Option Explicit
Sub First()
Dim FilenameCrnt As String
Dim WbookCrnt As Workbook
Debug.Print ThisWorkbook.Name
Debug.Print ThisWorkbook.Path
FilenameCrnt = Dir$(ThisWorkbook.Path & "\*.*")
Do While FilenameCrnt <> ""
Debug.Print FilenameCrnt
If FilenameCrnt = ThisWorkbook.Name Then
With ThisWorkbook
Debug.Print " Used range: " & .Worksheets(1).UsedRange.Address
End With
Else
If LCase(Right(FilenameCrnt, 3)) = "xls" Or _
LCase(Right(FilenameCrnt, 4)) = "xlsm" Or _
LCase(Right(FilenameCrnt, 4)) = "xlsx" Then
WbookCrnt = Workbooks.Open(ThisWorkbook.Path & "\" & FilenameCrnt)
With WbookCrnt
Debug.Print " Used range: " & .Worksheets(1).UsedRange.Address
End With
WbookCrnt.Close
WbookCrnt = Nothing ' Free resource
End If
End If
FilenameCrnt = Dir$
Loop
End Sub
Best of luck
I have an Excel sheet that draws data from other, closed Excel workbooks. Currently it works fine when I list out the closed workbook's entire path, but I'd like to use a variable, stored in a separate cell, as part of the path name.
For example, I am trying to reference a workbook called
workbook12.10.12.xls
In a separate workbook (we'll say the "active" workbook), I have a cell with formula
=INDEX('C:\Path[workbook12.10.12.xls]SHEET1'!$B$1:$B$5, MATCH("match text", 'C:\Path[workbook12.10.12.xls]SHEET1'!$A$1:$A$5, 0))
which finds the value in workbook12.10.12's B column corresponding to the cell in the A column that contains "match text." This works fine; however, I have a cell in the active workbook with the value
12.10.12
and would like to somehow reference this value in the INDEX function.
I can't have the other workbooks open, so the INDIRECT function won't help. Googling seems to suggest that Excel doesn't have a simple one-stop solution for this kind of thing... can someone help please? Thanks!
From Frank Kabel's 2004 post at Dicks Blog you could
Use Laurent Longre has developed the free add-in MOREFUNC.XLL which includes the function INDIRECT.EXT
Use SQL.REQUEST as described here *does not appear to be supported anymore and I am not clear if this could handle your INDEX\MATCH request
Use Harlan Grove’s PULL function
In addition you could:
Create a "dirty link" directly via code that enters a formula referring to the workbook you need
For pulling values - but not for working with ranges - you could use Walkenbach's ExecuteExcel4Macro XLM method
I think what you what to do is to find the specific record in the specific file (date named).
You may do it by a simple VBA code.
Suppose you are going to search for a record# say REC001 in A1, date file 12.10.12 at cell C1, and have the result to be display at cell A7
On the worksheet you want to enter input and get output, rightclick the sheet tab and select 'View code' and paste the following code:
Private Sub Worksheet_Change(ByVal Target As Range)
If Intersect(Target, Range("C1")) Is Nothing Then Exit Sub
Range("A7").Formula = "=INDEX('C:\TEMP\[workbook" & Range("C5").Value & ".xls]SHEET1'!$B$1:$B$5, MATCH(" & Range("A1").Value & ", 'C:\TEMP\[workbook" & Range("C5").Value & ".xls]SHEET1'!$A$1:$A$5, 0))"
End Sub
Then every time you edit C1, the formula will be updated.
Actually I don't think you should use INDEX function in your case. It is more simple to use a VLOOKUP. E.g.:
Range("A8").Formula = "=vlookup(" & Range("A1").Value & ",'C:\TEMP\[workbook" & Range("C5").Value & ".xls]SHEET1'!$A$1:$B$5,2,false)"
You will have to note on a few points:
1. you paste the code on the Sheet1 object (or the sheet name) but not to insert a new module
2. your path and filename for the target file is correct, including the .xls and .xlsx
3. your original file only cover to $B$5
4. on VBA, recommend you to save the file as .xlsm format
You can store a full reference including the file path to a range in a closed file in a name in excel (either directly or via VBA based on selections in different cells and using the Worksheet_Change procedure as above) and then refer to the file using the name in a formula as normal. This gets over the limitation in the INDIRECT function.
The VBA is very simple:
New_Ref = Sheets("Wells").Range("K6")
ActiveWorkbook.Names("MyWorkbook").RefersTo = "=" & New_Ref
The only trick is to be sure to include "=" in the name.
Names have a huge number of uses once you spot this. I have used this to get data from a closed file on a remote sharepoint site without any difficulty - I assume sharepoint deals with all the permissions.
I'm trying to create a dynamic link in Excel 2010. Below I have created a function that gives me the parent folder workbook to reference. When I try and add ' to the LEFT keyword excel does not accept it. What I'm trying to do is reference workbook in parent folder and want to make sure when the parent folder is moved all files stay linked.
My question is how to create a Link from the LEFT function below. Thanks
=LEFT(CELL("filename"),LARGE((MID(CELL("filename"),ROW(1:255),1)="\")*IFERROR(SEARCH("\",CELL("filename"),ROW(1:255)),0),2)) & CONCATENATE("[Book1.xlsx]Sheet1'!$A$1")
This should work, assuming your left formula is correct (not tested):
=INDIRECT("'["& LEFT(CELL("filename"),LARGE((MID(CELL("filename"),ROW(1:255),1)="\")*IFERROR(SEARCH(" \",CELL("filename"),ROW(1:255)),0),2))&"Book1.xlsx]Sheet1'!$A$1")
To create a link to a file you need to enter the full path and reference directly into a formula (INDIRECT won't work). One way to put a link to the parent folder in the active cell is with this VBA command:
activecell = "='" & activeworkbook.path & "\..\[Book1.xlsx]Sheet1'!$A$1"
Paths are stored relative to the workbook as stated in the response to your previous linked question. It's also possible to retrieve values from closed workbooks using a udf such as:
Function Eval(Text As String)
Set xl = CreateObject("excel.application")
eval = xl.ExecuteExcel4Macro(Application.ConvertFormula(Text, xlA1, xlR1C1, True))
Set xl = Nothing
End Function
or by downloading Laurent Longre's Morefunc.xll free add-in which has a function INDIRECT.EXT, (beware however that these methods are less efficient and links aren't created so won't update when folders are moved).
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.