Retrieve Column header depending on values present in an excel worksheet - excel

I have two worksheets ( sheet 1 and sheet 2) . Sheet 1 has 500X500 table. I want to
- Loop through each row ( each cell )
- Identify the cells which have a value ' X' in it
- Pick the respective column header value and store it in a cell in worksheet 2
For example
AA BB CC DD EE FF GG HH
GHS X
FSJ X
FSA X
MSD
SKD
SFJ X X
SFJ
SFM X
MSF X
Is there a way of writing a macro which will pull values in the form of
GHS -> GG
FSJ->DD
.
.
SFJ->BB HH
I have tried looping algorithms but does not seem to work. Could anyone please help me as I am very new to macros.

Try this .. Assumed that GHS, FSJ ... in column A
Sub ColnItem()
Dim x, y, z As Integer
Dim sItem, sCol As String
Dim r As Range
z = 1
For y = 1 To 500
sItem = Cells(y, 1)
sCol = ""
For x = 2 To 500
If UCase(Cells(y, x)) = "X" Then
If Len(sCol) > 0 Then sCol = sCol & " "
sCol = sCol & ColumnName(x)
End If
Next
If Len(sCol) > 0 Then
Sheets("Sheet2").Cells(z, 1) = sItem & " -> " & sCol
z = z + 1
End If
Next
End Sub
Function ColumnName(ByVal nCol As Single) As String
Dim sC As String
Dim nC, nRest, nDivRes As Integer
sC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
nC = Len(sC)
nRest = nCol Mod nC
nDivRes = (nCol - nRest) / nC
If nDivRes > 0 Then ColumnName = Mid(sC, nDivRes, 1)
ColumnName = ColumnName & Mid(sC, nRest, 1)
End Function

I have placed the values GG, etc., in separate columns of Sheet2, but the code could be modified to put all the information (for a row) in a single cell.
Sub GetColumnHeadings()
Dim ws1 As Worksheet, ws2 As Worksheet
Dim rng1 As Range, rng2 As Range, rng As Range
Dim off As Integer
Set ws1 = Worksheets("Sheet1")
Set ws2 = Worksheets("Sheet2")
Set rng1 = ws1.Range("A1").CurrentRegion
'CurrentRegion is the Range highlighted when we press Ctrl-A from A1
Set rng2 = ws2.Range("A1")
Application.ScreenUpdating = False
For Each rng In rng1
If rng.Column = 1 Then off = 0
If rng.Value = "X" Then
rng2.Value = rng.EntireRow.Cells(1, 1).Value
off = off + 1
rng2.Offset(0, off).Value = rng.EntireColumn.Cells(1, 1).Value
End If
'if we are looking at the last column of the Sheet1 data, and
'we have put something into the current row of Sheet2, move to
'the next row down (in Sheet2)
If rng.Column = rng1.Column And rng2.Value <> "" Then
Set rng2 = rng2.Offset(1, 0)
End If
Next rng
Application.ScreenUpdating = True
Set rng = Nothing
Set rng2 = Nothing
Set rng1 = Nothing
Set ws2 = Nothing
Set ws1 = Nothing
End Sub
I've also based in on the spreadsheet sample from the original post, where AA appears to be in cell A1.

Related

Excel VBA: Range Compare, For Each Loops, Nested IF Statements

Looking for assistance with the following:
Goal:
Compare cells in 2 defined ranges (same size) one by one. If they are the same then move on to the next set of cells. If not:
Input an integer (between 1 to 2000) in a corresponding cell within a 3rd range (same size as the other 2). Run this in a For loop until the cells in the first 2 ranges equal each other.
Once achieved, then move on to the next set of cells and so forth.
The code I've written up so far is outlined below but its not producing the right results. From what I can tell, the hCell value loops while the rest don't which is putting the If comparison conditions off...
Thank you for any help with this!
Sub Update()
Range("A1").Select
ActiveWindow.ScrollColumn = 1
ActiveWindow.ScrollRow = 1
Sheets("Funds").Select
Range("A1").Select
ActiveWindow.ScrollColumn = 1
ActiveWindow.ScrollRow = 1
'resets the "looping cells" from NR8 to PF207.
'Dim d As Integer
For d = 8 To 207
Range(Cells(d, 382), Cells(d, 422)) = ""
Next
Dim e As Integer
e = 1
Dim fRng As Range: Set fRng = Range("RB8:SP207")
Dim fCell As Range
Dim gRng As Range: Set gRng = Range("SU8:UI207")
Dim gCell As Range
Dim hRng As Range: Set hRng = Range("NR8:PF207")
Dim hCell As Range
Dim i As Integer
i = i
For e = 8 To 207
For Each fCell In fRng.Cells
For Each gCell In gRng.Cells
For Each hCell In hRng.Cells
If Cells(e, 191).Value = 0 Then
Exit For
Else
If (fCell.Value >= gCell.Value Or gCell.Value = "N/A") Then
Exit For
Else
For i = 0 To 2000
If fCell.Value >= gCell.Value Then
Exit For
Else
hCell.Value = i
If fCell.Value >= gCell.Value Then
Exit For
End If
End If
Next i
End If
End If
Next hCell, gCell, fCell
End If
Next e
Range("A1").Select
End Sub
I assume the values in the first two ranges are in some way dependent on the values in the third.
Option Explicit
Sub Update()
Const NCOLS = 41 ' 41
Const NROWS = 200 ' 200
Const LOOPMAX = 2000 ' 2000
Dim wb As Workbook, ws As Worksheet
Dim rng1 As Range, rng2 As Range, rng3 As Range
Dim cell1 As Range, cell2 As Range
Dim i As Long, r As Long, c As Integer, t0 As Double
t0 = Timer
Set wb = ThisWorkbook
Set ws = wb.Sheets(1)
Set rng1 = ws.Range("RB8")
Set rng2 = ws.Range("SU8")
Set rng3 = ws.Range("NR8")
'resets NR8 to PF207.
rng3.Resize(NROWS, NCOLS).Value = ""
Application.ScreenUpdating = False
For r = 1 To NROWS
Application.StatusBar = "Row " & r & " of " & NROWS
For c = 1 To NCOLS
Set cell1 = rng1.Offset(r - 1, c - 1)
Set cell2 = rng2.Offset(r - 1, c - 1)
If (cell1.Value <> cell2.Value) Or (cell2.Value = "N/A") Then
i = 0
Do
rng3.Offset(r - 1, c - 1) = i
i = i + 1
Loop Until cell1.Value = cell2.Value Or i > LOOPMAX
End If
Next c
Next r
Application.ScreenUpdating = True
MsgBox "Done", vbInformation, Int(Timer - t0) & " seconds"
rng3.Select
End Sub

Excel VBA to Copy Column from one sheet to another based on a second columns cell value

I tried this, which returned the rows I want, so a good start. But I really just need the value in Column B, not the entire row. What I really want is to list the value in column B if the value in column C is <>"" and column D <>"". Results in Quote sheet starting in cell C4.
Sub CopyQuoteValues()
Dim xRg As Range
Dim xCell As Range
Dim A As Long
Dim B As Long
Dim C As Long
A = Worksheets("Software Options").UsedRange.Rows.Count
B = Worksheets("Quote").UsedRange.Rows.Count
If B = 1 Then
If Application.WorksheetFunction.CountA(Worksheets("Quote").UsedRange) = 0 Then B = 0
End If
Set xRg = Worksheets("Software Options").Range("C17:C" & A)
On Error Resume Next
Application.ScreenUpdating = False
For C = 1 To xRg.Count
If CStr(xRg(C).Value) <> "" Then
xRg(C).EntireRow.Copy Destination:=Worksheets("Quote").Range("A" & B + 1)
B = B + 1
End If
Next
Application.ScreenUpdating = True
End Sub
Something like this should do what you need:
Sub CopyQuoteValues()
Dim wsOpt As Worksheet, wsQuote As Worksheet
Dim c As Range, rngDest As Range
Set wsOpt = Worksheets("Software Options")
Set wsQuote = Worksheets("Quote")
Set rngDest = wsQuote.Range("C4")
For Each c In wsOpt.Range("C17", wsOpt.Cells(wsOpt.Rows.Count, "C").End(xlUp)).Cells
If Len(c.Value) > 0 And Len(c.Offset(0, 1)) > 0 Then 'value in C and D ?
c.Offset(0, -1).Copy rngDest 'copy ColB
Set rngDest = rngDest.Offset(1, 0) 'next paste location
End If
Next c
End Sub

Color cells if same value found in a specified column

The following VBA code colors the cells in column B if the same value appears within column D.
I would like to also color column C. Changing the range to "B:D" does not work.
Sub HighlightCellIfValueExistsinAnotherColumn()
Dim ws As Worksheet
Dim x As Integer
Dim Find As Variant
Set ws = Worksheets("Sheet5")
For x = 1 To ws.Range("B" & Rows.Count).End(xlUp).Row
Set Find = ws.Range("D:D").Find(What:=ws.Range("B" & x).Value, LookAt:=xlWhole)
If Not Find Is Nothing Then
If ws.Cells(Find.Row, 6).Value = 0 And ws.Cells(Find.Row, 9).Value = 0 Then
ws.Range("B" & x).Interior.ColorIndex = 6
End If
End If
Next x
End Sub
Just duplicate the same command:
...
ws.Range("B" & x).Interior.ColorIndex = 6
ws.Range("C" & x).Interior.ColorIndex = 6
...
Add the D column if you wish.
EDIT:
I made adjustments to your code and annotate them to explain what the code means.
I used ListObjects/Table since that is what you have given as an example. In my testing, the code highlighted A-C columns on rows 2 and 5 only.
Sub HighlightCellIfValueExistsinAnotherColumn()
Dim ws As Worksheet
Dim nRow, sourceCol, findCol As Long
Dim FoundCell As Variant
Dim lo As ListObject
Dim LookupValue As String
Set ws = Worksheets("Sheet1")
'Note: set a table name for your entire table range
'I assumed "Table1" as its name so it is arbitrary
Set lo = ws.ListObjects("Table1")
'column to iterate
sourceCol = lo.ListColumns("List2").Index
'column to search
findCol = lo.ListColumns("Animals").Index
'for each row of the list object
For nRow = 1 To lo.ListRows.Count
'what value to search
LookupValue = lo.DataBodyRange.Cells(nRow, sourceCol)
'try to find the value and return the cell
Set FoundCell = lo.DataBodyRange.Columns(findCol).Find(LookupValue, LookAt:=xlWhole)
'if value is found
If Not FoundCell Is Nothing Then
'check colums 6 and 9 if zero
If ws.Cells(FoundCell.Row, 6).Value = 0 And ws.Cells(FoundCell.Row, 9).Value = 0 Then
'color em yellow "List1", "List2" & "List3" for the current row
lo.DataBodyRange.Cells(nRow, sourceCol).Interior.ColorIndex = 6
lo.DataBodyRange.Cells(nRow, sourceCol + 1).Interior.ColorIndex = 6
lo.DataBodyRange.Cells(nRow, sourceCol - 1).Interior.ColorIndex = 6
End If
End If
Next nRow
End Sub

Need help copy/pasting in Excel VBA from one workbook to another

I need to find out how to write some basic code that will take each cell's value (which will be an ID number) from a selected range, then match it to a cell in a master workbook, copy said cell's entire row, then insert it into the original document in place of the ID number. Here's the kicker: certain ID numbers may match with several items, and all items that have that number must be inserted back into the document. Here's an example:
Master Document Workbook
A B C D A B C D
1 a ab ac 2
2 b bc bd 3
2 b be bf
3 c cd de
I would select the cells containing 2 and 3 in the Workbook, which after running the code would give me this:
Workbook
A B C D
2 b bc bd
2 b be bf
3 c cd de
Here's what I have going on so far but it's a total mess. The only thing it's managed to successfully do is store the selected range in the Workbook I want to paste to. It won't compile past that because I don't understand much of the syntax in VBA:
Sub NewTest()
Dim rng As Range
Dim FirstRow As Range
Dim CurrentCol As String
Dim FirstRowVal As Integer
Dim CurrentColVal As Variant
Dim rngOffset As Range
CurrentCol = "Blah"
Set FirstRow = Application.InputBox("Select the row containing your first raw material", Type:=8)
FirstRowVal = FirstRow.Row
Set rng = (Application.InputBox("Select the cells containing your IC numbers", "Obtain Materials", Type:=8))
Set rngOffset = rng.Offset(0, FirstRowVal)
CurrentColVal = rng.Column
Call CopyPaste
End Sub
Sub CopyPaste()
Dim Blah As Range
Set x = Workbooks.Open("Workbook Path")
Workbooks.Open("Workbook Path").Activate
Set y = Workbooks.Open("Master Path")
Workbooks.Open("Master Path").Activate
With x
For Each Cell In rng
x.Find(rng.Cell.Value).Select
If Selection.Offset(0, -1) = Selection Then
Selection.EntireRow.Copy
Selection = Selection.Offset(0, -1)
Else
Selection.EntireRow.Copy
Blah = Selection
End If
Workbooks.Open("Workbook Path").Activate
Sheets("Formula Sheet").Select
Blah.Insert (rng.Cell)
End
Sheets("sheetname").Cells.Select
Range("A1").PasteSpecial
'Sheets("sheetname").PasteSpecial
.Close
End With
With x
.Close
End With
End Sub
Would very much appreciate anyone who could help point me in the right direction. Thanks.
I'll bite, you can use the output array to populate any range on any worksheet.
Sub FindAndMatch()
Dim arrMatchFrom() As Variant, arrMatchTo() As Variant, arrOutput() As Variant
Dim i As Integer, j As Integer, counter As Integer
counter = 0
arrMatchFrom = Range("A2:D6")
arrMatchTo = Range("G2:G3")
For i = LBound(arrMatchTo, 1) To UBound(arrMatchTo, 1)
For j = LBound(arrMatchFrom, 1) To UBound(arrMatchFrom, 1)
If arrMatchTo(i, 1) = arrMatchFrom(j, 1) Then
counter = counter + 1
ReDim Preserve arrOutput(4, counter)
arrOutput(1, counter) = arrMatchTo(i, 1)
arrOutput(2, counter) = arrMatchFrom(j, 2)
arrOutput(3, counter) = arrMatchFrom(j, 3)
arrOutput(4, counter) = arrMatchFrom(j, 4)
End If
Next
Next
For i = 1 To counter
For j = 1 To 4
Debug.Print arrOutput(j, i)
Cells(9 + i, j) = arrOutput(j, i)
Next
Next
End Sub

Transposing Sets of Columns on Top of Each Other in Excel

So I have multiple sets of 3 columns. Each set is always in the same column order ("SKU", "Sales". "Date".)
I am wondering is there is a VBA script or other method that would do the following:
1.) Copy G:I
2.) Paste into A:C
3.) Copy J:L
4.) Paste into A:C (Underneath G:I's data)
5.) Copy M:O
6.) Paste into A:C (underneath J:L's data)
7.) Repeat (I would like it to repeat every 3 columns forever, but if that's not possible I'll manually input the columns if I have
to.)
This is a visual of what I'm looking for: http://i.imgur.com/AagLIm8.png
I also uploaded the workbook in case you need it for reference: https://www.dropbox.com/s/wea2nr4xbfo4934/Workbook.xlsx?dl=0
Thanks for the help!
The code below does what you want, and I've included some ".select" lines to help you understand. I suggest you step through it to become clear, as in the animated gif. Then, remove all the ".select" lines of code.
Option Explicit
Sub moveData()
Dim rSource As Range, rDest As Range, r As Range
Dim tbl As Range, rowNum As Integer
Const colNum = 3
Set rDest = Range("A1")
Set rSource = Range("G1")
Set r = rSource
While r <> ""
Set r = Range(r, r.End(xlDown))
Set tbl = Range(r, r.Offset(0, colNum - 1))
tbl.Select
Set tbl = Range(tbl, tbl.End(xlDown).Offset(1, 0))
tbl.Select
tbl.Copy
rDest.Select
rDest.PasteSpecial (xlPasteAll)
Set rDest = rDest.Offset(tbl.Rows.Count, 0)
Set r = r(1, 1)
r.Select
Set r = r.Offset(0, colNum)
r.Select
Wend
End Sub
try to do this:
Sub CopyColumns()
Dim actualRow As Integer
Dim actualColumn As Integer
Dim rowFrom As Integer
Dim myColumns As Integer
Dim startColumn As Integer
myColumns = 3 'the number of columns before start repeating (in your case is SKU, Sales, Date, so there are 3 columns)
startColumn = 7 'the column where start de data. In your example is the Column G
actualRow = 1
actualColumn = 1
rowFrom = 1
Dim eoRows As Boolean
eoRows = False
While eoRows = False
'verify if there's no more data
If Cells(rowFrom, startColumn) = "" Then
eoRows = True
Else
'verify if there's no more row
While Cells(rowFrom, startColumn) <> ""
For i = startColumn To startColumn + myColumns - 1
Cells(actualRow, actualColumn) = Cells(rowFrom, i)
actualColumn = actualColumn + 1
Next
rowFrom = rowFrom + 1
actualRow = actualRow + 1
actualColumn = 1
Wend
rowFrom = 1
startColumn = startColumn + myColumns
End If
Wend
End Sub

Resources