Range Multiplication VB.NET (What is wrong with this code?) - vb.net

(VB Express Level: Beginner)
I want to do following,
A column from Workbook 1
a
b
c
d
A column from Workbook2
e
f
g
h
Output to a single cell
ae+bf+cg+dh
(The output is a Sumproduct.)
There are 44 rows in workbook 1 and 44 rows in workbook 2. But there are 3 columns in workbook 1 and 104 columns in workbook 2. Each column in workbook 3 must be multiplied with 104 columns from workbook 2.
Following is my effort, which writes sames values in all the cells of a column. My understanding is my for loop is wrong somewhere. But I am not able to figure out what is wrong.
'link to workbooks
oWB5 = oXL5.Workbooks.Open("D:\1.xlsx")
oWB6 = oXL6.Workbooks.Open("D:\2.xlsx")
oWB7 = oXL7.Workbooks.Open("D:\outputs.xlsx")
'link to worksheets
oSheet5 = oWB5.Worksheets("Inputs")
oSheet6 = oWB6.Worksheets("Coef")
oSheet7 = oWB7.Worksheets("Sheet1")
' ranges to be considerd,
' oWB5 range C22 to C66
' oWB6 range C3 to C47
' oWB7 range C2 to C104 (because there are 104 columns in oWB6)
'multiplication of ranges
For j = 3 To 47
For i = 2 to 104
For k = 2 to 4
For l = 22 to 66
oSheet7.Cells(i, k).Value = (oSheet5.Cells(l, k).value * oSheet6.Cells(j, i+1).value) + (oSheet5.Cells(l+1, k).value * oSheet6.Cells(j + 1, i+1).value)
Next
Next
Next
Next
Help will be really appreciated. I am struggling with this for two days now.

Here is a simple method using the Excel's SUMPRODUCT formula. This way you let Excel do the dirty work for you. The advantage of this is that it saves you a lot of looping :)
TRIED AND TESTED
Imports Excel = Microsoft.Office.Interop.Excel
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim xlApp As New Excel.Application
Dim oWB5 As Excel.Workbook = xlApp.Workbooks.Open("C:\1.xlsx")
Dim oWB6 As Excel.Workbook = xlApp.Workbooks.Open("C:\2.xlsx")
Dim oWB7 As Excel.Workbook = xlApp.Workbooks.Open("C:\outputs.xlsx")
Dim oSheet7 As Excel.Worksheet = oWB7.Worksheets("Sheet1")
With oSheet7
For i = 1 To 8
For j = 1 To 104
Dim Col1Nm As String = Split(.Cells(, j).Address, "$")(1)
Dim Col2NM As String = Split(.Cells(, i).Address, "$")(1)
.Cells(i, j).Value = xlApp.Evaluate("=SUMPRODUCT(([1]Inputs!" & Col1Nm & "1:" & _
Col1Nm & "44)*([2]Coef!" & Col2NM & "1:" & Col2NM & "44))")
Next
Next
End With
'~~> Close workbook and quit Excel
oWB5.Close (False)
oWB6.Close (False)
oWB7.Close (True)
xlApp.Quit()
'~~> Clean Up
releaseObject (oWB5)
releaseObject (oWB6)
releaseObject (oWB7)
releaseObject (xlApp)
MessageBox.Show("done")
End Sub
Private Sub releaseObject(ByVal obj As Object)
Try
System.Runtime.InteropServices.Marshal.ReleaseComObject (obj)
obj = Nothing
Catch ex As Exception
obj = Nothing
Finally
GC.Collect()
End Try
End Sub
End Class
IMP NOTE: If your actual file names are not 1.xlsx and 2.xlsx then change this part of the code
xlApp.Evaluate("=SUMPRODUCT(([1]Inputs!" & Col1Nm & "1:" & _
Col1Nm & "44)*([2]Coef!" & Col2NM & "1:" & Col2NM & "44))")
Replace
[1] by [Actual File Name]
[2] by [Actual File Name]
Inputs by [Actual Sheet Name] and
Coef by [Actual Sheet Name]

Thanks for re-posting this question with more detail.
I've written a loop bellow with comments that i believe achieves what you're looking to do.
'link to workbooks
oWB5 = oXL5.Workbooks.Open("D:\1.xlsx")
oWB6 = oXL6.Workbooks.Open("D:\2.xlsx")
oWB7 = oXL7.Workbooks.Open("D:\outputs.xlsx")
'link to worksheets
oSheet5 = oWB5.Worksheets("Inputs")
oSheet6 = oWB6.Worksheets("Coef")
osheet7 = oWB7.Worksheets("Sheet1")
' ranges to be considerd,
' oWB5 range C22 to C66
' oWB6 range C3 to C47
' oWB7 range C2 to C104 (because there are 104 columns in oWB6)
'multiplication of ranges
Dim lngOutputCounter As Long
For i = 1 To 104 'for each column WB6
For j = 1 To 3 'for each column WB5
lngOutputCounter = 0 'reset to 0
For k = 1 To 44 'loop through 44 rows
'multiply the two cells and keep a running total
'- 21+k to start at row 22, 2+k to start at row 3, 2+j and 2+i because columns start at C
lngOutputCounter = lngOutputCounter + oSheet5.Cells(21 + k, 2 + i).Value * oSheet6.Cells(2 + k, 2 + j).Value
Next k
'whatever column sheet2 was on becomes row here, j is still the same column (1-3)
'- i+i to output to row 2 first, 2+j to output to column C first
osheet7.Cells(1 + i, 2 + j).Value = lngOutputCounter
Next j
Next i

Related

End(xlDown) for single rows

I have a macro that is working 99% of the time, but giving me trouble with one portion. I have data that is split into different size groups depending on certain parameters. The groups range from 1 row to as many at 10+. I am trying to copy each of the "groups" and paste into a template sheet and save which I've figured out.
Row Column B Column C
1 ASDF a
2 SDF a
3 WIRO a
4 VNDH a
5
6 FIJDK b
7 DFKIEL b
8
9 DLFKD c
10
11 OYPTK d
12 SSAODKJ d
13 SKJSJ d
Where I'm having trouble is Row 9 where Column b B = DLFKD and Column C = C
Desired Output:
Copy only row 9
Actual Output:
Copying Rows 9- 11
Existing Macro:
Data begins on Row 5.
Sub templatecopy()
Dim x As Workbook
Dim y As Workbook
Dim N As Long
Dim name As String
'## Open both workbooks first:
Set x = ActiveWorkbook
'Set R
R = 5
'start Loop
Do Until N = 96
Set y = Workbooks.Open("F:\Logistics Dashboard\Customs Macro\Cover Sheet Template.xlsx")
'set N
N = Range("B" & R).Cells(1, 1).End(xlDown).Row
'Now, copy Container Numbers from x and past to y(template):
x.Sheets("Sheet1").Range("B" & R & ":C" & N).Copy
y.Sheets("Sheet1").Range("A14").PasteSpecial
'save as Name of Vessel
name = "F:\Logistics Dashboard\Customs Macro\" & y.Sheets("Sheet1").Range("A14").Value & ".xlsx"
ActiveWorkbook.SaveAs Filename:=name
'Close template after saving to reset:
y.Close
'set R equal to new row to start
R = N + 2
Loop
End Sub
The issue is with how I am setting "N". Its having trouble distinguishing Row 9 where its just one row of data.
With the correct sheet selected this line of code should select the ranges on your sheet:
Thisworkbook.Worksheets("Sheet1").range("B:C").specialcells(xlcelltypeconstants,23).select
You'll need to add another line to account for formula as well as constants.
Public Sub FindRegionsOnSheet()
Dim sAddress As String
Dim aAddress() As String
Dim vItem As Variant
Dim x As Long
Dim wbTarget As Workbook
Dim wsSource As Worksheet
Dim wsTarget As Worksheet
Set wsSource = ThisWorkbook.Worksheets("Sheet1")
Set wbTarget = Workbooks.Open("F:\Logistics Dashboard\Customs Macro\Cover Sheet Template.xlsx")
Set wsTarget = wbTarget.Worksheets("Sheet1")
'Find all ranges of constant & formula values in column B:C.
With wsSource.Columns(2).Resize(, 2)
On Error Resume Next
sAddress = .SpecialCells(xlCellTypeConstants, 23).Address(0, 0) & ","
sAddress = sAddress & .SpecialCells(xlCellTypeFormulas, 23).Address(0, 0)
If Right(sAddress, 1) = "," Then sAddress = Left(sAddress, Len(sAddress) - 1)
On Error GoTo 0
End With
'Place within an array.
If Not sAddress = vbNullString Then
If InStr(1, sAddress, ",") = 0 Then
ReDim aAddress(0 To 0)
aAddress(0) = "'" & wsSource.Name & "'!" & sAddress
Else
aAddress = Split(sAddress, ",")
For x = LBound(aAddress) To UBound(aAddress)
aAddress(x) = "'" & wsSource.Name & "'!" & aAddress(x)
Next x
End If
End If
''''''''''''''''''''''''''''''''''''''''
'Not sure how what you're doing once moved to the Target book......
'Think this is correct, but test first...
''''''''''''''''''''''''''''''''''''''''
For Each vItem In aAddress
wsTarget.Cells.Clear
Range(vItem).Copy Destination:=wsTarget.Range("A14")
wbTarget.SaveCopyAs "F:\Logistics Dashboard\Customs Macro\" & wbTarget.Sheets("Sheet1").Range("A14") & ".xlsx"
Next vItem
wbTarget.Close
End Sub
The 23 in the SpecialCells indicates what types of cells to include in the result:
XlSpecialCellsValue constants Value
xlErrors 16
xlLogical 4
xlNumbers 1
xlTextValues 2
These values can be added together to return more than one type (total = 23). The default is to select all constants or formulas, no matter what the type.... so probably don't need the 23 at all.

VBA autofilling multidimensional arrays

As a beginner, I would like to ask if it is possible in VBA to autofill formulas in a multidimensional array.
Ι thought and wrote this code and it works with values but not with formulas.
I think that what I am trying to do is very ambitious for my skills
Sub eucldiist()
Dim e(10,10) As Double, i As Integer, j As Integer
For i = 1 To 10
For j = 1 To 10
e(i, j).FormulaArray = "=sqrt((offset('Data1'!$Q$14,$BD$5(offset(i)) -
offset('Data1'!$Q$14,$BD$5(offset(j))^2+ ((offset('Data1'!$U$14,
$BD$5(offset(i))-OFFSET('Data1'!$U$14,$BD$5(offset(j)))^2)"
Next j
Next i
Sheets("Calculations").Select: Range("A20").Select
For i = 1 To 10
For j = 1 To 10
ActiveCell.Value = e(i, j)
ActiveCell.Offset(0, 1).Select
Next j
ActiveCell.Offset(1, -10).Select
Next i
End Sub
Is it possible what I am trying to do?
check this out. put some formulas in a20:j29 before hand
Option Explicit
Sub test()
Dim aaa As Variant
aaa = Range("a20").Resize(10, 10).Formula
Stop ' now examine aaa in "locals" window
' maybe all you want is this
range("a20").Resize(10,10).FormulaArray = "=SQRT((OFFSET(DATA1!Q14,BD5,0)-OFFSET(DATA1!Q14,BD7,0))^2+((OFFSET(DATA1!U14,BD5,0)-OFFSET(DATA1!U14,BD7,0))^2))"
End Sub
i think that this is what you want
NOTE: formula uses absolute addressing, so a column or row insert will break it
delete $ from formula to make it use relative addressing
Sub eucldiist()
Dim base As Range
Set base = Sheets("Calculations").Range("A20")
' Set base = ActiveSheet.Range("A20")
Dim formula As String
Dim i As Integer, j As Integer
For i = 0 To 9 ' rows
For j = 0 To 9 ' columns
formula = "=sqrt(" _
& " (offset('Data1'!$Q$14,$BD$" & 5 + i & ",0) - offset('Data1'!$Q$14,$BD$" & 7 + j & ",0))^2" _
& " + (offset('Data1'!$U$14,$BD$" & 5 + i & ",0) - offset('Data1'!$U$14,$BD$" & 7 + j & ",0))^2" _
& ")"
' Debug.Print formula
base.Offset(i, j) = formula
Next j
Next i
End Sub

Program Error Subscript out of Range ... Tried On Error Resume

I am having problem with the subscript out of range with this line:
datasheet = wbook.Sheets("Month and Year")
I have tried to use On Error Resume but I might have done it wrong.
This code is suppose to establish month and year so that later, I am able to use it when I create a new sheet and refer to the previous one named similarly "Forecast Month Year". afterwards, it looks at 3 columns to validate that it is the row that it wants to copy and paste and then establishes it on the respective sheet.
Sub repeatingrows()
Dim wbook As Workbook
Set wbook = Application.ActiveWorkbook
'CHECKS THE MONTH TO INCREASE THE YEAR
Dim datasheet As Worksheet
datasheet = wbook.Sheets("Month and Year")
Dim m As Integer
Dim y As Integer
Dim t As Integer
For t = 2 To 13
For m = 1 To 13
If m = 13 Then
y = y + 1
m = 1
End If
Next m
m = .Cells(t, 1)
.Cells(t, 1) = .Cells(t, 2)
Next t
'MAKE NEW SHEET AND RENAME IT
Dim oldsheet As Worksheet
Dim newsheet As Worksheet
Set oldsheet = Application.ActiveSheet
oldsheet = Sheets("Forecast " & m & " " & y)
newsheet = Sheets("Forecast " & (m + 1) & " " & y)
Sheets.Add.Name = "Forecast " & (m + 1) & " " & y
'CHECK IF the 3 columns ARE SIMILAIR TO PREVIOUS PAGE
Dim rrow As Integer
For rrow = 3 To 500
If Sheets(3).Cell(rrow, 2) = Sheets(2).Cell(rrow, 2) Then
If Sheets(3).Cell(rrow, 5) = Sheets(2).Cell(rrow, 5) Then
If Sheets(3).Cell(rrow, 6) = Sheets(2).Cell(rrow, 6) Then
With newsheet
oldsheet.Range(oldsheet.Cells(rrow, 16), oldsheet.Cells(rrow, 19)).Copy
.Range(.Cells(b, a), .Cells(99, 51)).PasteSpecial xlPasteValues, xlPasteSpecialOperationAdd
End With '^COPY AND PASTES THE ROW
Else
End If
Else
End If
Else
End If
Next rrow
End Sub
try:
Set datasheet = wbook.Sheets("Month and Year")
and check the spelling of the sheetnameand check that the sheet exists in the proper workbook.and don't use .Cells() without a With
(there may be other errors)

Loop macro and change ranges with each loop

I’m starting with a worksheet “Med” that has formulas/data/formatting in cells A4:P9. I need to copy those cells to cell A10 (6 rows down). I then need to fill in some of the cells from information in another worksheet “Data”. I need to repeat this the same number of times as the count of Data!(A:A) -1 dropping down 6 rows each time I copy the information.
The data that I need to fill in comes from the Sheet "Data" and moves over one column for each copy in Sheet “Med”.
I have the code to make the first copy, but don’t have any idea where to go from here. Looking at the code below the next copy would go to A16 (6 rows down from A10).
The ranges from the worksheet “Med” would also increase by 6 rows and the columns would stay the same.
The ranges from the worksheet “Data” would move over on column and the row numbers would stay the same.
Jordan
Sub Macro1()
Dim wsData As Worksheet
Dim wsMed As Worksheet
Set wsData = Sheets("Data")
Set wsMed = Sheets("Med")
'Copy data set
wsMed.Range("A4:P9").Copy wsMed.Range("A10") 'Set Premium Values
wsMed.Range("M11").Value = wsData.Range("C20").Value
wsMed.Range("M12").Value = wsData.Range("C21").Value
wsMed.Range("M13").Value = wsData.Range("C22").Value
wsMed.Range("M14").Value = wsData.Range("C23").Value 'Set Assumptions
wsMed.Range("L11").Value = wsData.Range("C24").Value
wsMed.Range("L12").Value = wsData.Range("C25").Value
wsMed.Range("L13").Value = wsData.Range("C26").Value
wsMed.Range("L14").Value = wsData.Range("C27").Value
End Sub
This macro runs the code three times
Sub Macro1()
Dim wsData As Worksheet
Dim wsMed As Worksheet
Set wsData = Sheets("Data")
Set wsMed = Sheets("Med")
Dim i As Integer, j As Integer, x As Integer
i = 10
j = 3
'Copy data set
For x = 1 To 3 ' run 3 times
wsMed.Range("A4:P9").Copy wsMed.Cells(i, 1) 'Set Premium Values
wsMed.Range("M" & i + 1).Value = wsData.Cells(20, j).Value
wsMed.Range("M" & i + 2).Value = wsData.Cells(21, j).Value
wsMed.Range("M" & i + 3).Value = wsData.Cells(22, j).Value
wsMed.Range("M" & i + 4).Value = wsData.Cells(23, j).Value 'Set Assumptions
wsMed.Range("L" & i + 1).Value = wsData.Cells(24, j).Value
wsMed.Range("L" & i + 2).Value = wsData.Cells(25, j).Value
wsMed.Range("L" & i + 3).Value = wsData.Cells(26, j).Value
wsMed.Range("L" & i + 4).Value = wsData.Cells(27, j).Value
i = i + 6
j = j + 1
Next x
End Sub

Excel VBA taking user input to check a cell across multiple sheets and save specific sheets for later use

I'm new to VBA, and trying to write a program in excel that will allow me to manually input a row and column into a program. The program should then check the specified cell in multiple sheets to see if it's a 1 or 0. If it's a 0, then I need the specific worksheet that it was in to be saved and identified later in an output box.
Below is what I have so far. The parts I'm unsure about are the saving the specified worksheet, and specifying the cell used to check from the input box (IE if Cj.range(D H) vs Cj.cell(DH) etc.).
Option Explicit
Sub Trial1()
Dim Hr As Single
Dim D As Single
Do
D = InputBox("Please enter the day you would like to study. Monday = A, Tuesday = B, Wed = C, Thurs = D, Fri = E, Sat = F, Sun = G.")
Hr = InputBox("Please enter the hour you would like to study in military time.")
If Hr >= 7 Or Hr <= 22 Then Exit Do
Loop
Call worksheet1()
End Sub
Sub worksheet1()
Dim Availability() As String
Dim C1 As Worksheet
Dim C2 As Worksheet
Dim C3 As Worksheet
Dim C4 As Worksheet
Dim C5 As Worksheet
Dim C6 As Worksheet
Dim C7 As Worksheet
Dim C8 As Worksheet
Dim C9 As Worksheet
Set C1 = ActiveWorkbook.Sheets("3043")
Set C2 = ActiveWorkbook.Sheets("2222")
Set C3 = ActiveWorkbook.Sheets("2205")
Set C4 = ActiveWorkbook.Sheets("3138")
Set C5 = ActiveWorkbook.Sheets("1011")
Set C6 = ActiveWorkbook.Sheets("1012")
Set C7 = ActiveWorkbook.Sheets("1016")
Set C8 = ActiveWorkbook.Sheets("1219")
Set C9 = ActiveWorkbook.Sheets("2245")
Do
For j = 1 To 9
If Cj.Range(DHr) = 0 Then
ReDim Preserve Availability(0 To UBound(Availability) + 1) As String
End If
Next j
Possible Alternative
'For i = 1 To N
'If Worksheets(i).Cells(H, D).Value = 0 Then MsgBox ("There is room available in room sheet" & i & ".")
'If Worksheets(i).Cells(H, D).Value = 1 Then MsgBox ("ROOM")
'Next i
EDIT: I clarified the msgbox at the end: Either NO places available, or list of 'places' (which happens to be the worksheet name).
Here is an example of how to spin through the desired sheets and find which ones have a zero in the desired row/column. You could pass the list back to the calling subroutine, or just deal with it where they are found.
Option Explicit
Sub Trial1()
Dim Hr As Long
Dim D As Long
Do
D = InputBox("Please enter the day you would like to study. Monday = 1, Tuesday = 2, Wed = 3, Thurs = 4, Fri = 5, Sat = 6, Sun = 7.")
Hr = InputBox("Please enter the hour you would like to study in military time.")
If Hr >= 7 Or Hr <= 22 Then Exit Do
Loop
Call Check_Sheets(Hr, D)
End Sub
Function Check_Sheets(lRow As Long, lCol As Long)
Dim Availability() As String
Dim i As Integer
Dim ws As Worksheet
Dim iAvail As Integer
Dim strMSG As String
' Note: I included the "'" as a delimiter in case the combined numbers give a false sheet name.
Const SheetNames = "'3043'2222'2205'3138'1011'1012'1016'1219'2245"
For Each ws In ThisWorkbook.Sheets ' Find all worksheets
If InStr(1, SheetNames, "'" & ws.Name) > 0 Then ' Is this a sheet we want?
If ws.Cells(lRow, lCol).value & "" = 0 Then ' Is the cell = 0 (warning: make sure no null values else!)
iAvail = iAvail + 1 ' Count as available
ReDim Preserve Availability(iAvail)
Availability(iAvail) = ws.Name ' Save sheet name
End If
End If
Next ws
' List Available Sheets
If iAvail > 0 Then
strMSG = "Area 1, 2 and 3 as saved in Array" & vbCrLf & vbCrLf 'This is the part I'm unsure about (TheBanks)
For i = 1 To iAvail
Debug.Print "Available: " & Availability(i)
strMSG = strMSG & Availability(i) & vbCrLf
Next
MsgBox strMSG, vbOKOnly, "The Following Areas Are Available"
Else
MsgBox "There were NO places available", vbOKOnly, "None Available"
End If
End Function
I think what you are trying to do with the workbook names would be better done as an array. Although it isn't a whole solution, there are other problems, like if the user inputs lower case.
Dim C(0 To 8) As String
Dim tRange As String
Dim tSheet As String
C(0) = "3043"
C(1) = "2222"
C(2) = "2205"
C(3) = "3138"
C(4) = "1011"
C(5) = "1012"
C(6) = "1016"
C(7) = "1219"
C(8) = "2245"
For j = 0 To 8
tSheet = C(j) ' of course you can skip this line and just insert C(j) into Sheets()
tRange = Chr(34) & D & Hr & Chr(34)
If Sheets(tSheet).Range(tRange) = 0 Then
ReDim Preserve Availability(0 To UBound(Availability) + 1) As String
End If
Next j