Trying to make this work for multiple cells - excel

I have made this program that creates groups of 4 cells on sheets 2 and 3 depending on the value of a cell in sheet 1.
Sub Two_of_Two()
Dim Two_by_Two(1 To 6) As Range
Dim Diag1 As Range
Dim Diag2 As Range
Dim Horiz1 As Range
Dim Horiz2 As Range
Dim Vert1 As Range
Dim Vert2 As Range
Dim Share1 As Range
Dim Share2 As Range
Dim TopLeft As Range
Dim BottomRight As Range
Dim Black As Integer
Dim White As Integer
Black = 255
White = 0
Set Diag1 = Sheet1.Range("E17:F18")
Set Diag2 = Sheet1.Range("H17:I18")
Set Horiz1 = Sheet1.Range("E21:F22")
Set Horiz2 = Sheet1.Range("H21:I22")
Set Vert1 = Sheet1.Range("E24:F25")
Set Vert2 = Sheet1.Range("H24:I25")
Set Two_by_Two(1) = Diag1
Set Two_by_Two(2) = Diag2
Set Two_by_Two(3) = Horiz1
Set Two_by_Two(4) = Horiz2
Set Two_by_Two(5) = Vert1
Set Two_by_Two(6) = Vert2
Dim Cell As Range
Dim Subpixel As Range
For Each Cell In Sheet1.Range("A1")
Set Share1 = Sheet2.Range("A1:B2")
Set Share2 = Sheet3.Range("A1:B2")
Share1.Value = Two_by_Two(Int((6 - 1 + 1) * Rnd + 1)).Value
If Cell.Value >= 127.5 Then
Share2.Value = Share1.Value
ElseIf 127.5 > Cell.Value Then
For Each Subpixel In Share1
If Subpixel.Value = Black Then
Sheet3.Cells(Subpixel.Row, Subpixel.Column) = White
ElseIf Subpixel.Value = White Then
Sheet3.Cells(Subpixel.Row, Subpixel.Column) = Black
End If
Next Subpixel
End If
Next Cell
End Sub
I want to make it so that this works for multiple cells. Say once the for loop goes on to the next cell A2, it inputs values into the next 2x2 group of cells along. So if A1 in Sheet 1 corresponds to the range ("A1:B2") in Sheets 2 and 3, then B1 in Sheet 1 would be ("C1:D2") in Sheets 2 and 3.
Can someone please help me with this? Thanks.

I've cleaned up the code quite a bit and looped the Two_by_Two array.
Sub Two_of_Two()
Dim Two_by_Two(1 To 6) As Range
Dim Diag1 As Range: Set Diag1 = Sheet1.Range("E17:F18")
Dim Diag2 As Range: Set Diag2 = Sheet1.Range("H17:I18")
Dim Horiz1 As Range: Set Horiz1 = Sheet1.Range("E21:F22")
Dim Horiz2 As Range: Set Horiz2 = Sheet1.Range("H21:I22")
Dim Vert1 As Range: Set Vert1 = Sheet1.Range("E24:F25")
Dim Vert2 As Range: Set Vert2 = Sheet1.Range("H24:I25")
Dim Share1 As Range: Set Share1 = Sheet2.Range("A1:B2")
Dim Share2 As Range: Set Share2 = Sheet3.Range("A1:B2")
Dim TopLeft, BottomRight, Cell, Subpixel As Range
Dim Black, White, rndval As Integer
Dim i As Long
Black = 255
White = 0
Set Two_by_Two(1) = Diag1
Set Two_by_Two(2) = Diag2
Set Two_by_Two(3) = Horiz1
Set Two_by_Two(4) = Horiz2
Set Two_by_Two(5) = Vert1
Set Two_by_Two(6) = Vert2
rndval = Int(6 * Rnd + 1)
Share1.Value = Two_by_Two(rndval).Value
If Sheet1.Cells(1, 1) >= 127.5 Then
Share2.Value = Share1.Value
Else
Share2.Value = Sheet1.Cells(1, 1)
End If
For Each Subpixel In Share1
If Subpixel.Value = Black Then
Sheet3.Cells(Subpixel.Row, Subpixel.Column) = White
ElseIf Subpixel.Value = White Then
Sheet3.Cells(Subpixel.Row, Subpixel.Column) = Black
End If
Next Subpixel
End Sub

Related

How to turn a column of data into an 8x12 grid?

I'm trying to put values from 1 column into an 8x12 grid.
With the first value starting in the top left of the grid, moving to the right 12 cells, then offsetting 1 row from starting cell and having the data continue filling cells in this format.
I'm trying to replace
roneWS.Range("E6:N6") = Application.Transpose(ptWS.Range("B4:B13"))
roneWS.Range("C7:N7") = Application.Transpose(ptWS.Range("B14:B25"))
roneWS.Range("C8:N8") = Application.Transpose(ptWS.Range("B26:B37"))
roneWS.Range("C9:N9") = Application.Transpose(ptWS.Range("B38:B49"))
roneWS.Range("C10:N10") = Application.Transpose(ptWS.Range("B50:B61"))
roneWS.Range("C11:N11") = Application.Transpose(ptWS.Range("B62:B73"))
roneWS.Range("C12:N12") = Application.Transpose(ptWS.Range("B74:B85"))
roneWS.Range("C13:N13") = Application.Transpose(ptWS.Range("B86:B97"))
with an array/loop.
I came up with:
Dim ptWS As Worksheet, roneWS As Worksheet, rtwoWS As Worksheet, rthreeWS As Worksheet, rfourWS As Worksheet
Dim ptRng As Range, destRng As Range
Dim i As Integer
Dim ptArr() As Variant
Set ptWS = ThisWorkbook.Worksheets("PT")
Set roneWS = ThisWorkbook.Worksheets("WS1")
Set rtwoWS = ThisWorkbook.Worksheets("WS2")
Set rthreeWS = ThisWorkbook.Worksheets("WS3")
Set rfourWS = ThisWorkbook.Worksheets("WS4")
i = 4
Set ptRng = ptWS.Range("B4:B97") 'data that needs to be moved to other worksheets B4:B97 = 1st WS, C4:C97 = 2nd WS, D4:D97 = 3rd WS, E4:E97 = 4th WS
Set destRng = roneWS.Range("E6") 'destination range for WS1-WS4 starts at E6
ptArr = ptRng.Value 'setting all values for the WS1 to ptArr
For i = LBound(ptArr) To UBound(ptArr)
If ptArr(i, 1) = ptWS.Cells(14, 2) Then 'move my way across the columns until I hit Col O then, offset back to Col C and repeat until the end (N13) is reached
Set destRng = destRng.Offset(1, -12)
destRng = ptArr(i, 1)
Set destRng = destRng.Offset(0, 1)
ElseIf ptArr(i, 1) = ptWS.Cells(26, 2) Then
Set destRng = destRng.Offset(1, -12)
destRng = ptArr(i, 1)
Set destRng = destRng.Offset(0, 1)
ElseIf ptArr(i, 1) = ptWS.Cells(38, 2) Then
Set destRng = destRng.Offset(1, -12)
destRng = ptArr(i, 1)
Set destRng = destRng.Offset(0, 1)
ElseIf ptArr(i, 1) = ptWS.Cells(50, 2) Then
Set destRng = destRng.Offset(1, -12)
destRng = ptArr(i, 1)
Set destRng = destRng.Offset(0, 1)
ElseIf ptArr(i, 1) = ptWS.Cells(62, 2) Then
Set destRng = destRng.Offset(1, -12)
destRng = ptArr(i, 1)
Set destRng = destRng.Offset(0, 1)
ElseIf ptArr(i, 1) = ptWS.Cells(74, 2) Then
Set destRng = destRng.Offset(1, -12)
destRng = ptArr(i, 1)
Set destRng = destRng.Offset(0, 1)
ElseIf ptArr(i, 1) = ptWS.Cells(86, 2) Then
Set destRng = destRng.Offset(1, -12)
destRng = ptArr(i, 1)
Set destRng = destRng.Offset(0, 1)
Else: destRng = ptArr(i, 1)
Set destRng = destRng.Offset(0, 1)
End If
Next i
It gives me what I want for WS1. However I have to repeat this for the 3 other worksheets.
For the other 3 worksheets, the total range is the same as posted above, just offset by 1 column.
WS1 = ptWS.Range("B4:B97")
WS2 = ptWS.Range("C4:C97")
WS3 = ptWS.Range("D4:D97")
WS4 = ptWS.Range("E4:E97")
The destination starting point on all 4 worksheets are the same Range(E6").
How do I add a loop through the worksheets once all cells on WS1 have been set, while also offsetting the column by 1 from ptWS. I'm wondering if this can be done without copy/pasting the existing array code 3 more times and just changing the ranges.
I achieved the same result by looping through the data on ptWS by using a series of Do Until loops but then eventually ran into the same issue.
Here's one appraoch:
Sub Tester()
Dim i As Long
For i = 1 To 4
ColToMatrix ThisWorkbook.Worksheets("PT").Range("B4:B97").Offset(0, i - 1), _
ThisWorkbook.Worksheets("WS" & i).Range("C6")
Next i
End Sub
'pass in the column to be mapped and the top-left destination cell for the matrix
Sub ColToMatrix(rngCol As Range, rngTL As Range)
Dim arr, mtx(1 To 8, 1 To 12), i As Long, r As Long, c As Long, n As Long
arr = rngCol.Value
For i = 1 To UBound(arr, 1)
n = i + 2 'account for starting 3 cells in
r = 1 + ((n - 1) \ 12)
c = ((n - 1) Mod 12) + 1
mtx(r, c) = arr(i, 1)
Next i
rngTL.Resize(8, 12).Value = mtx
End Sub
To do this, better way is doing a sub to transpose data, and then call it for every worksheet.
I'm excluding roneWS.Range("E6:N6") = Application.Transpose(ptWS.Range("B4:B13")) because it's not part of the 7x12 array, due to different size (it's 10 values, not 12).
So we focus on 7x12, this part of your code:
roneWS.Range("C7:N7") = Application.Transpose(ptWS.Range("B14:B25"))
roneWS.Range("C8:N8") = Application.Transpose(ptWS.Range("B26:B37"))
roneWS.Range("C9:N9") = Application.Transpose(ptWS.Range("B38:B49"))
roneWS.Range("C10:N10") = Application.Transpose(ptWS.Range("B50:B61"))
roneWS.Range("C11:N11") = Application.Transpose(ptWS.Range("B62:B73"))
roneWS.Range("C12:N12") = Application.Transpose(ptWS.Range("B74:B85"))
roneWS.Range("C13:N13") = Application.Transpose(ptWS.Range("B86:B97"))
This sub will as for:
A source range like ptWS.Range("B14:B97"), 84 values (7x12)
A destiny range like roneWS.Range("C7:N13"), a 7x12 grid
The code is:
Sub GET_VALUES(ByVal vRngSource As Range, ByVal vRngDestiny As Range)
Dim vMatriz As Variant
Dim ZZ As Long
Dim ThisColumn As Long, ThisRow As Long
ThisColumn = 1
ThisRow = 1
vMatriz = vRngSource.Value
For ZZ = 1 To UBound(vMatriz) Step 1
vRngDestiny.Cells(ThisRow, ThisColumn).Value = vMatriz(ZZ, 1)
If ThisColumn = 12 Then
ThisColumn = 1
ThisRow = ThisRow + 1
Else
ThisColumn = ThisColumn + 1
End If
Next ZZ
Erase vMatriz
End Sub
To call it, you can just do:
Sub test()
GET_VALUES Range("B14:B97"), Range("C7:N13")
End Sub
Now you just need to call it once for every worksheet. I would use a For each loop combined with Select Case, so you can choose for every worksheet what to do, like this:
Sub TEST()
Application.ScreenUpdating = False
Dim WK As Worksheet
Dim ptWS As Worksheet
Set ptWS = ThisWorkbook.Worksheets("PT")
For Each WK In ThisWorkbook.Worksheets
Select Case WK.Name
Case "WS1"
GET_VALUES ptWS.Range("B14:B97"), WK.Range("C7:N13")
WK.Range("E6:N6") = Application.Transpose(ptWS.Range("B4:B13"))
Case "WS2"
GET_VALUES ptWS.Range("C14:C97"), WK.Range("C7:N13")
WK.Range("E6:N6") = Application.Transpose(ptWS.Range("C4:C13"))
Case "WS3"
GET_VALUES ptWS.Range("D14:D97"), WK.Range("C7:N13")
WK.Range("E6:N6") = Application.Transpose(ptWS.Range("D4:D13"))
Case "WS4"
GET_VALUES ptWS.Range("E14:E97"), WK.Range("C7:N13")
WK.Range("E6:N6") = Application.Transpose(ptWS.Range("E4:E13"))
Case Else
'we do nothing
End Select
Next WK
Application.ScreenUpdating = True
End Sub
Hope you can adapt this to your needs.

Using the LinEst function and return values in a column of variable length

I am trying to use the LinEst function to take values from a range of rows of data and input them into a new sheet under some headings. I only want to do this for a particular number of rows (up to row number defined as "c". My VBA skills are very basic.
Sub Button7_Click()
Sheets.Add.Name = "Down Sweep Power Law"
Dim xrng As Range, yrng As Range
Dim i As Long
Dim Rng As Range
Dim l As Long
Dim k As Long
Dim i2 As Long
Dim c As Long
Dim j As Long
Dim drop As Range
Dim drop2 As Range
Dim DownSweep As Chart, UpSweep As Chart, cht As Chart
Dim ws As Worksheet, smallest
Dim dsws As Worksheet
Set ws = Worksheets("Template") '<< use variables for worksheets!
Set dsws = Worksheets("Down Sweep Power Law")
Set Rng = ws.Range(ws.Range("B11"), ws.Range("B11").End(xlDown))
smallest = WorksheetFunction.Small(Rng, 1)
l = Rng.Find(what:=smallest, LookIn:=xlValues, lookat:=xlWhole).Row
k = Rng.Rows.Count
c = l - 10
Set xrng = ws.Range("C11:CP11")
Set yrng = ws.Range("C201:CP201")
Set drop = dsws.Range("A2")
Set x2rng = xrng.Offset(1, 0)
Set y2rng = yrng.Offset(1, 0)
Set drop2 = drop.Offset(1, 0)
dsws.Range("A1").Value = "(n-1) Value"
dsws.Range("B1").Value = "log(k) Value"
dsws.Range("C1").Value = "(n-1) Value"
dsws.Range("D1").Value = "n Value"
dsws.Range("E1").Value = "R Value"
If i < c Then
Set drop = Application.LinEst(Log10(yrng), Log10(xrng), True, False)
i = i + 1
End If
ITERATE:
If i < c Then
Set drop2 = Application.LinEst(Log10(y2rng), Log10(x2rng), True, False)
x2rng = x2rng.Offset(1, 0)
y2rng = y2rng.Offset(1, 0)
drop2 = drop2.Offset(1, 0)
i = i + 1
GoTo ITERATE
End If
End Sub
the code runs but when I go on the created sheet, there is a #NAME error (2029) and no values are present.
Is there a way to fix this?
Any help would be appreciated.
I think you have omitted a step from your plan. LinEst returns an array and you want to assign the values in that array to the range Drop. You can't assign the array directly to the range. Please try this code.
Option Explicit
Sub Button7_Click()
Dim xrng As Range, yrng As Range
Dim Drop As Range
Dim Arr As Variant ' LinEst result array
Dim Rng As Range
Dim R As Long
Dim l As Long
Dim k As Long
Dim i2 As Long
Dim c As Long
Dim j As Long
Dim DownSweep As Chart, UpSweep As Chart, cht As Chart
Dim ws As Worksheet, Smallest As Variant
Dim dsws As Worksheet
Set ws = Worksheets("Template") '<< use variables for worksheets!
Sheets.Add.Name = "Down Sweep Power Law"
Set dsws = Worksheets("Down Sweep Power Law")
Set Rng = ws.Range(ws.Range("B11"), ws.Range("B11").End(xlDown))
Smallest = WorksheetFunction.Small(Rng, 1)
l = Rng.Find(what:=Smallest, LookIn:=xlValues, LookAt:=xlWhole).Row
k = Rng.Rows.Count
c = l - 10
Set xrng = ws.Range("C11:CP11")
Set yrng = ws.Range("C201:CP201")
Set Drop = dsws.Range("C2:CP2").Offset(0, -2)
dsws.Range("A1").Value = "(n-1) Value"
dsws.Range("B1").Value = "log(k) Value"
dsws.Range("C1").Value = "(n-1) Value"
dsws.Range("D1").Value = "n Value"
dsws.Range("E1").Value = "R Value"
Do While R < c
Arr = Application.LinEst(Log10(yrng), Log10(xrng), True, False)
Drop.Value = Arr ' or perhaps: = Application.Transpose(Arr)
Set xrng = xrng.Offset(1, 0)
Set yrng = yrng.Offset(1, 0)
Set Drop = Drop.Offset(1, 0)
R = R + 1
Loop
End Sub
I don't know what kind of array LinEst will return. You may have to transpose the result.
I also tried to improve your management of ranges. However, the code is entirely untried, for lack of data. There may be logical errors in my code as well as typos but the syntax should be sound. It may not take you all the way over the finish line but I hope it will help you in your quest.

VBA Code to add multiple series to a scatter graph - run time 1004 error

I am writing a code to add multiple series to a line graph. I have also put in a counter to make two separate graphs when a minimum value corresponding to a row is met. My VBA skills are very basic and I get a run time 1004 error at the asterisked line:
Dim xrng As Range
Dim yrng As Range
Dim x2rng As Range
Dim y2rng As Range
Dim i As Integer
Dim Rng As Range
Dim l As Integer
Dim k As Integer
Dim i2 As Integer
Worksheets("Template").Activate
Dim lv As String
lv = Worksheets("Template").Range(Worksheets("Template").Range("B11"), Worksheets("Template").Range("B11").End(xlDown)).Find(WorksheetFunction.Small(Worksheets("Template").Range(Worksheets("Template").Range("B11"), Worksheets("Template").Range("B11").End(xlDown)), 1), , , 1).Address
Range(lv).Select
l = ActiveCell.Row
k = Worksheets("Template").Range(Worksheets("Template").Range("B11"), Worksheets("Template").Range("B11").End(xlDown)).Rows.Count
i = 1
i2 = 1
Set xrng = Worksheets("Template").Range("C11:CP11")
Set yrng = Worksheets("Template").Range("C201:CP201")
Set x2rng = xrng.Offset(1, 0)
Set y2rng = xrng.Offset(1, 0)
Dim Chart1 As Chart
Set Chart1 = Charts.Add
With Chart1
Chart1.ChartType = xlXYScatter
Chart1.SeriesCollection.NewSeries
Chart1.SeriesCollection(1).XValues = xrng
Chart1.SeriesCollection(1).Values = yrng
End With
i = i + 1
ITERATE:
If i < l Then
With Chart1
Chart1.SeriesCollection.NewSeries
Chart1.SeriesCollection(i).XValues = x2rng
' pretend the next line is bold
Chart1.SeriesCollection(i).Values = y2rng
x2rng = x2rng.Offset(1, 0)
y2rng = y2rng.Offset(1, 0)
i = i + 1
GoTo ITERATE
End With
End If
If i < k Then
Dim Chart2 As Chart
Set Chart2 = Charts.Add
With Chart2
Chart2.ChartType = xlXYScatter
Chart2.SeriesCollection.NewSeries
Chart2.SeriesCollection(1).XValues = x2rng
Chart2.SeriesCollection(1).Values = y2rng
End With
End If
i2 = i2 + 1
ITERATE2:
If i < k Then
Chart1.SeriesCollection.NewSeries
Chart1.SeriesCollection(i2).XValues = x2rng
Chart1.SeriesCollection(i2).Values = y2rng
x2rng = x2rng.Offset(1, 0)
y2rng = y2rng.Offset(1, 0)
i2 = i2 + 1
GoTo ITERATE2
End If
I am not sure why I am getting this error.
Any help would be appreciated.
Thanks,
Judoo

Loop to create Object excel vba

I tried to get the unique value of each column in the range "RD" and display them in single column. I need to create an object ("scripting.Dictionary") where there are just as many as the number of columns in Range "RD". I tried this code but it resulted in "Run time error 13".
Private Sub CommandButton1_Click()
Range(Me.RefEdit1).Name = "RD"
Range(Me.RefEdit2).Name = "OT"
Dim d As Object, c As Variant, i As Long, s As Long
Dim JK As Long
Dim o As Collection
JK = Range("RD").Columns.Count
Set d = CreateObject("Scripting.Dictionary")
For k = 0 To JK + 1
d.Item(k) = CreateObject("Scripting.Dictionary").Item(k)
c = Range("RD").Columns(k + 1)
If d.Exists(k) Then
d.Item(k) = d.Item(k) + 1 'increment
Else
d.Item(k) = 1 'set as 1st occurence
End If
For i = 1 To UBound(c, 1)
d.Item(k)(c(i, 1)) = 1
Next i
Range("OT").Cells((k * 5) + 2, 2).Resize(d.Item(k).Count) = Application.Transpose(d.Item(k).Keys)
Range("OT").Cells((k * 5) + 2, 2).Resize(d.Item(k).Count).Sort Key1:=Range("OT").Cells((k * 5) + 2, 2).Resize(d.Item(k).Count)
Next k
End Sub
I'm adding some code below to help loop through a list, looking for unique values, and adding them to a new column. In my example, I enclose the entire functionality into a single loop for efficiency. I'm also adding the unique values to a new column in Sheet2 starting with cell A1.
Let me know if you need any additional help.
EDITED CODE BASED ON A MISUNDERSTANDING:
Private Sub CommandButton1_Click()
Dim oDict As Object
Dim rngToScrub As Range
Dim rngNewColumnToStoreUnique As Range
Dim oCol As Range
Dim cel As Range
Set rngToScrub = Range(Me.RefEdit1.Value)
Set rngNewColumnToStoreUnique = Sheet2.Range("A1")
For Each oCol In rngToScrub.Columns
Set oDict = CreateObject("Scripting.Dictionary")
For Each cel In oCol.Cells
If oDict.exists(cel.Value) Then
'Do Nothing for Now
Else
oDict.Add cel.Value, 0
rngNewColumnToStoreUnique.Value = cel.Value
Set rngNewColumnToStoreUnique = rngNewColumnToStoreUnique.Offset(1)
End If
Next cel
Set oDict = Nothing
Next oCol
End Sub
Old code: Misunderstood requirements
Private Sub CommandButton1_Click()
Dim oDict As Object
Dim rngToScrub As Range
Dim rngNewColumnToStoreUnique As Range
Dim cel As Range
Set oDict = CreateObject("Scripting.Dictionary")
Set rngToScrub = Range(Me.RefEdit1.Value)
Set rngNewColumnToStoreUnique = Sheet2.Range("A1")
For Each cel In rngToScrub
If oDict.exists(cel.Value) Then
'Do Nothing for Now
Else
oDict.Add cel.Value, 0
rngNewColumnToStoreUnique.Value = cel.Value
Set rngNewColumnToStoreUnique = rngNewColumnToStoreUnique.Offset(1)
End If
Next cel
End Sub

Changing colour of a single point with VBA

I'm comparing two series and if the value of the 2nd series is less than the 1st at a given XValue, I want to make the bar for that 2nd series red. I tried following some other forum answers and got to this but now I'm stuck...
Public Sub Bar_Colour()
Dim c As Chart
Dim p As Series
Dim a As Series
Dim iPoint As Long
Dim nPoint As Long
Set c = ActiveChart
Set s = ActiveChart.SeriesCollection(1)
Set a = ActiveChart.SeriesCollection(2)
nPoint = s.Points.Count
For iPoint = 1 To nPoint
If a.Points(iPoint).Value < s.Points(iPoint).Value Then
a.Points(iPoint).Interior.Color = RGB(255, 0, 0)
End If
Next iPoint
End Sub
Thanks!
Public Sub Bar_Colour()
Dim c As Chart
Dim p As Series
Dim a As Series
Dim iPoint As Long
Dim nPoint As Long
Set c = ActiveChart
Set s = ActiveChart.SeriesCollection(1)
Set a = ActiveChart.SeriesCollection(2)
nPoint = s.Points.Count
For iPoint = 1 To nPoint
If a.Values(iPoint) < s.Values(iPoint) Then
a.Points(iPoint).Interior.Color = RGB(255, 0, 0)
End If
Next iPoint
End Sub

Resources