Use Absolute Naming for Worksheets when used with VBA - vba

I have the following problem: In one of my excel files, i have the following worksheets: One in which I have a number of formulas, one with the data for the current month (which gets copied&pasted from another source into there), and a couple of worksheets that are used as some sort of archive.
I use a little VBA macro to move the data from the current month into the archive.
Sheets("Aktueller Monat").Cells.Cut
Sheets("1").Activate
Range("A1").Select
ActiveSheet.Paste
The moving part of it works fine. The problem is now that everytime i move the current month into the archive, it updates all the formula in my calc sheet so that they are now referencing the archive (which I don't want to, since the formulas should be calculating the new current month instead)
For example, this
=ZĂ„HLENWENN('Aktueller Monat'!$C:$C;"RSS*")
becomes this
=ZĂ„HLENWENN('1'!$C:$C;"RSS*")
and I don't want that.
Can anybody help me?

Instead of using Cut and Paste, use Copy and PasteSpecial, followed by Clear or ClearContents. In the example below I paste the values and number formats, but you can adjust this to your needs using different values of the XlPasteType Enumeration:
Dim oSourceRange As Range, oTargetRange As Range
Set oSourceRange = Worksheets("Aktueller Monat").UsedRange
Set oTargetRange = Worksheets("1").Range("A1")
oSourceRange.Copy
oTargetRange.PasteSpecial xlPasteValuesAndNumberFormats
oSourceRange.ClearContents

Related

Copy relevant rows and paste to new worksheet

I have multiple sheets which I am looking to copy and paste the relevant cells from rows into a new worksheet. The defining factor is whether the rows are "Live" which is determined by whether today falls between the "start date" and "end date" columns. For all rows that are "live" certain cells on that row should then be copy pasted to the bottom of the list on the new worksheet. I would then repeat these steps for the other worksheets so that the new worksheet essentially contains a summary of all "live" lines from the other sheets.
I then ultimately need to create a button so I can re-run this at the end of each day.
Hoping you can help!
You've defined and explained what you want to do nicely. So the next step would be to start researching the actions you want the code to do:
Start with how to copy rows:
http://www.bluepecantraining.com/copying-moving-rows-columns-excel-vba/
Next is how to find the last used row in a worksheet:
https://powerspreadsheets.com/excel-vba-last-row/
Next is to apply your condition on what rows to copy:
Using VBA to check if a date is between two dates
Next is how to create a for loop that runs the code the desired number of times:
https://www.excel-easy.com/vba/loop.html (a tip is to use the LastRow that you defined via the second link i posted. eg: "For x = 1 To LastRow")
And lastly is how to assign a macro to a button or shape:
https://wellsr.com/vba/2017/excel/how-to-assign-a-macro-to-a-shape-in-excel/
Try to build a code with the help of these links. If you get stuck, come back and show us what you've created and where the problem is. I (aswell as and many others) would love to help you on from there.

Selecting columns based on specific text strings

I'm trying to put together a macro which will select certain columns and paste them into a new sheet. The problem is that columns tend to be added and deleted as people see fit which throws off the absolute referencing.
I have been trying to tinker with the basic macro produced using the macro recorder but I haven't had any luck selecting columns based on their contents. I have a sheet that is generated from our database daily with changing fields. For example, I would like to select just the Part #, Cost, and Contact fields but the addition of the IDN today threw my old macro off.
So far, I've tried to use basic excel find functions like vlookup, index against a list of constants and the find function below but none seem to work. Is there something I am missing here to select the column with my desired text?
Columns(find("Part #")).Select
Firstly, be careful with .Select and it looks like you're not fully qualifying your references to the worksheet so take note of the full Workbook.Worksheet.Range type referencing below.
Here's your quick fix:
Public Sub Test()
'the Range approach
ThisWorkbook.Worksheets("Sheet1").Rows(1).Find(What:="Part #", LookAt:=xlWhole).EntireColumn.Copy
ThisWorkbook.Worksheets("Sheet2").Range("A1").PasteSpecial xlPasteValuesAndNumberFormats 'or xlPasteAll to include formulas
End Sub
Using entire column ranges isn't usually the best idea. It will work, but only as long as you remember to paste your copied column into the first row of the destination worksheet every time.
Here's the better option (IMO):
Convert your data to a Table (know as a ListObject in VBA) by clicking "format as table" on the home tab of the ribbon. It's now much easier to reference your column - just do it by name, no need to use Find.
Public Sub Test()
'the ListObject approach
ThisWorkbook.Worksheets("Sheet1").ListObjects("MyTable").ListColumns("Part #").Copy
ThisWorkbook.Worksheets("Sheet2").Range("A1").PasteSpecial xlPasteValuesAndNumberFormats 'or xlPasteAll to include formulas
End Sub
You need to know the name of your table (I called it MyTable here), which you can do by clicking on "Table" on the ribbon when your table is selected
You need to specifically find the column, then you can paste off to a destination location, such as:
Sheets("Source").Columns(Sheets("Source").Rows(1).Find("Part #").Column).Copy Sheets("Dest").Cells(1,1)

Running an IF statement for all worksheets

I have data arranged in Excel like so:
Year|Trade Flow|Commodity Code|Commodity|Qty Unit|Qty|Net Weight|Trade Value
I have an IF formula:
=IF(D2=D1,0,IF(D3=D2,ABS(I3-I2),I2))
which I need to run for all the worksheets in the file, using VBA.
I am assuming you know how to find the last cell (plenty of examples on this site), or have a fixed size.
I used column H just for an example.
for each sh in sheets
sh.range("H2:H20").Formula="=IF(D2=D1,0,IF(D3=D2,ABS(I3-I2),I2))"
next
alter this to suit your needs

Find/replace conditionally formatted cells

I've been using a conditional format formula =OR(B2=B1,B2=B3) to highlight consecutive duplicates. I then use format painter to copy the formula to all columns in my excel table.
I have set up a button that will, amongst other things, copy a workbook into a new workbook. I now want to include the above formula in this macro. My final objective is to replace all of the cells found with this formula with an asterisk (*).
I first tried to just pop the formula into the macro as a starting point -
For Each sh In Destwb.Worksheets
With sh.UsedRange.FormatConditions _
.Add(Type:=xlExpression, Formula1:="=OR(B2=B1,B2=B3)")
.Interior.Color = RGB(198, 239, 206)
End With
Next sh
But this just makes a mess of seemingly randomly highlighted cells. I'm not sure where I've gone wrong. Even column B highlights are all wrong. Could the header in B1 affect this? It doesn't when I use the CF normally. How can I expand the CF into all columns uniquely?
Finally, how do I go about working a replacement of formatted cells into this formula? Or is there a quicker/easier way to meet this end-goal?
I didn't realise I could add custom text in that way. That's moved me a good couple of steps forward.
Taking Balinti's suggestion into consideration I've tried a workaround. I was making a couple of assumptions that turned out to be wrong. I have been able to enter the CF into the Array of data that I have in my original workbook. It's not as simple as putting it into a table, but by manually selecting the range in each column and inputting the CF I have made it work.
I also wasn't sure if the formatting would carry through to the new worksheet as I have used the Paste Special command to convert the array formula to values in the new sheet. It does, however, carry the formatting across which is very handy.
It's not the perfect solution for me but it appears to be working so far. I still need to test what happens when I change the date and get updated data. It would still be interesting to know if I can move this formatting into my macro though. Any tips?

Excel Reference External Sheet

An excel question for you gurus. I've tried searching high and low and haven't come up with an effective solution.
I'm trying to create a formula that will lookup a value in an external sheet. I'm using the SUMPRODUCT formula and it works perfectly. Formula is below:
=SUMPRODUCT(--('File\Path\[file.xlsx]SheetName!$D$1:$D$1000=$B3), --('File\Path\[file.xlsx]SheetName'!$O$1:$O$1000=$A3), 'File\Path\[file.xlsx]SheetName'!$Q$1:$Q$1000)
The issue I'm running into, however, is that the source file is updated every day. Although the workbook name stays the same, the sheet name changes. A random string gets assigned to the source sheet name each time it is updated. As such SheetName becomes SheetName ase341.
Is there a way to have the formula read the external sheet number instead of the name? I want the formula to update regardless of the sheet name. If there's no way to read the sheet position is there a way to change the sheet name via a formula in an external workbook?
Usage Example
I have a workbook (analysis) and it pulls data from another workbook (source). Source is updated every day with new data. The data in Source is updated by downloading a report from the internet and saving over the old source file. As such, the file name stays the same but whatever is inside the file is always different (including the sheet name). There is always only ever one sheet in the Source with the same number of columns, always in the same position.
There is a really neat way to refer to a block of cells in an external workbook in which the sheetname or even the block address may vary. Say we have:
=SUM('C:\Users\James\Desktop\[Book1.xlsx]Sheet1'!$B$2:$B$9)
however the sheetname may vary. First assign a Defined Name to the block in Book1 (say XXX)
Then we can use:
=SUM('C:\Users\James\Desktop\Book1.xlsx'!XXX)
It does not matter if the sheetname changes, the Defined Name will change with it!
Your issue would be most efficiently solved with VBA, but if you're just getting started this might not be the best route.
You can get the sheetname or filename with just a formula, though:
http://www.ozgrid.com/VBA/return-sheet-name.htm