Issue on create vlookup function and check the condition? - vba

I am try to create vlookup function for compare date with in two sheet to find out given date is available in sheet2. If it is not available in sheet 2 means we can create other wise tell message already available for that code
mycode
Sub Button1_Click()
Dim ColNum As Integer
Dim Line As String
Dim LineValues() As Variant
Dim OutputFileNum As Integer
Dim PathName As String
Dim RowNum As Integer
Dim SheetValues() As Variant
PathName = Application.ActiveWorkbook.Path
OutputFileNum = FreeFile
Open PathName & "\Upload Additional PDP.csv" For Output Lock Write As #OutputFileNum
Print #OutputFileNum, "Dist_Code" & "," & "Actual_PDP_Date (dd/MM/yyyy)" & "," & "Reason_Code"
Dim rng1 As Range, rng2 As Range, i As Integer, j As Integer
End Sub
for ex:
1
+--------+--------+---------------+---------+--------+
| A | B | C | D | E |
+--------+--------+---------------+---------+--------+
| Code | Name | Description | Price | Cost | Date
+--------+--------+---------------+---------+--------+
| AC33 | Prod 1 | Prod Desc 1 | 3.99 | 2.00 | 16/7/2014
+--------+--------+---------------+---------+--------+
| AC34 | Prod 2 | Prod Desc 2 | 4.99 | 3.00 | 16/7/2014
+--------+--------+---------------+---------+--------+
| AC35 | Prod 3 | Prod Desc 3 | 5.99 | 4.00 | 16/7/2014
+--------+--------+---------------+---------+--------+
2
+--------+--------+---------------+---------+
| A | B | C | D |
+--------+--------+---------------+---------+
| Code | Name |Updated Price | Cost | Date
+--------+--------+---------------+---------+
| AC33 | Prod 1 | 16.99 | |
+--------+--------+---------------+---------+
| AC37 | Prod 2 | 18.99 | |
+--------+--------+---------------+---------+
| AC38 | Prod 3 | 21.99 | |
+--------+--------+---------------+---------+

Use the IsError function to test the result of the VLOOKUP, here's something to get you started:
If IsError(Application.VLookup(Range("A1"), Range("C:C"), 1, False)) Then
Debug.Print "Not found"
Else
Debug.Print "Found"
End If

Related

Join two excel table

I have two excel table structure and order
structure contain
Product | Component | Order_Quantity
A | C1 | 1
A | C2 | 3
A | C3 | 3
B | C1 | 1
B | C4 | 2
C | C1 | 1
D | C2 | 3
C | C3 | 3
order contain
Order_n | Product | Quantity
1 | A | 10
2 | B | 10
3 | A | 10
4 | C | 10
6 | B | 10
How can i join the two table in excel 2013 (without power pivot or another add-in) to see result like this :
Order_n | Product | Order_Qty | component | Quantity | Total_QTY
1 | A | 10 | C1 | 1 | 10
1 | A | 10 | C2 | 3 | 30
1 | A | 10 | C3 | 3 | 30
2 | B | 10 | C1 | 1 | 10
2 | B | 10 | C4 | 2 | 20
3 | A | 10 | C1 | 1 | 10
3 | A | 10 | C2 | 3 | 30
3 | A | 10 | C3 | 3 | 30
4 | C | 10 | C1 | 1 | 10
4 | C | 10 | C3 | 3 | 30
6 | B | 10 | C1 | 1 | 10
6 | B | 10 | C4 | 2 | 20
You'll have to use VBA.
This should work... Couldn't test the whole thing, so let me know if it works.
Sub JoinTables()
Dim cn
Dim rs
Dim strFile As String
Dim strCon As String
Dim strSQL As String
Dim strTbl1 As String
Dim strTbl2 As String
Dim JoinField As String
Dim Table1Name As String
Dim Table2Name As String
Dim Table3Address As String
Dim Table1Worksheet As String
Dim Table2Worksheet As String
Dim Table3Worksheet As String
' CHANGE THESE!
Table1Name = "structure": Table1Worksheet = "Sheet1" ' Name of table and name of the worksheet it is on
Table2Name = "order": Table2Worksheet = "Sheet1"
Table3Address = "A2": Table3Worksheet = "Sheet2" ' The result
JoinField = "Product"
' ==================================
strFile = ThisWorkbook.FullName
strCon = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & strFile _
& ";Extended Properties=""Excel 12.0;HDR=Yes;IMEX=1"";"
Set cn = CreateObject("ADODB.Connection")
Set rs = CreateObject("ADODB.Recordset")
cn.Open strCon
strTbl1 = " [" & Table1Worksheet & "$" & Replace(ThisWorkbook.Worksheets(Table1Worksheet).ListObjects(Table1Name).Range.AddressLocal, "$", "") & "] AS T1 "
strTbl2 = " [" & Table2Worksheet & "$" & Replace(ThisWorkbook.Worksheets(Table2Worksheet).ListObjects(Table2Name).Range.AddressLocal, "$", "") & "] AS T2 "
strSQL = "SELECT * FROM " & strTbl1 & " LEFT JOIN " & strTbl2 & " ON T1." & JoinField & "=T2." & JoinField
rs.Open strSQL, cn
ThisWorkbook.Worksheets(Table3Worksheet).Range(Table3Address).CopyFromRecordset rs
rs.Close
cn.Close
End Sub

VB.NET LINQ Group By Multiple Columns

I have the following LINQ code which has a syntax error and i've no idea how to fix it
Dim query =
From row In mainDatatable.AsEnumerable
'the syntax Error is in the following line
Group row By new { row.Field(Of Double)("cprice") , row.Field(Of Integer)("ccategory")}
Into ProductGroups
'**************************
Dim grpNumber = 1
For Each grp In query
For Each row In grp.ProductGroups
row.SetField("gnum", grpNumber)
Next
grpNumber += 1
Next
End Sub
so what am i doing wrong?
Here is how the table looks like and i want to group by the columns cprice and ccategory
+---------------+---------------+-----------+------+
| Product Name | cprice | ccategory | gnum |
+---------------+---------------+-----------+------+
| Skirt Red | 99 | 1 | |
| Jeans Blue | 49 | 2 | |
| Jeans Black | 49 | 2 | |
| Skirt Blue | 99 | 1 | |
| T-shirt White | 20 | 2 | |
| T-shirt Green | 20 | 2 | |
| Jeans Grey | 49 | 2 | |
+---------------+---------------+-----------+------+
Try this:
new with { Key.Price = row.Field(Of Double)("cprice") ,
Key.Category = row.Field(Of Integer)("ccategory")
Uisng the Key modifier, this creates an anonymous type that implements equality based on equality of its members.

SQL add processed ids to a single cell seperated with a comma

i have the following sql query to get an idea of what it does please read the description below
select catalogid, numitems, allitems - numitems ignoreditems
from (
select i.catalogid,
sum(case when (ocardtype in ('PayPal','Sofort') OR
ocardtype in ('mastercard','visa') and
odate is not null) AND NOT EXISTS (
select * from booked b
where b.ignoredoid = o.orderid
) then numitems
else 0 end) numitems,
sum(numitems) allitems
from orders o
join oitems i on i.orderid=o.orderid
group by i.catalogid
) X
and the following sql tables
oitems table
+---------+-----------+----------+
| orderid | catalogid | numitems |
+---------+-----------+----------+
| O737 | 353 | 1 |
| O738 | 364 | 4 |
| O739 | 353 | 3 |
| O740 | 364 | 6 |
| O741 | 882 | 2 |
| O742 | 224 | 5 |
| O743 | 224 | 2 |
+---------+-----------+----------+
Orders table
+-----------------+------------+------------+
| orderid | ocardtype | odate |
+-----------------+------------+------------+
| O737 | Paypal | | 'OK
| O738 | MasterCard | 01.02.2012 | 'OK
| O739 | MasterCard | 02.02.2012 | 'OK
| O740 | Visa | 03.02.2012 | 'OK
| O741 | Sofort | | 'OK
| O742 | | | 'ignore because ocardtype is empty
| O743 | MasterCard | | 'ignore because Mastercard no odate
+-----------------+------------+------------+
the reusltant datatable
+-----------+----------+--------------+
| catalogid | numitems | ignoreditems |
+-----------+----------+--------------+
| 353 | 4 | 0 |
| 364 | 10 | 0 |
| 882 | 2 | 0 |
| 224 | 0 | 7 |
+-----------+----------+--------------+
idea is to sum the numitems column for products that have the same catalogid depinding on the data in the oitems table with the following conditions
if ocardtype is empty then ignore the numitems and consider it as 0
in the sum and sum the ignored items to the ignoreditems column
if ocardtype for some order is MasterCard or Visa and the odate is
empty then ignore the numitems and consider it as 0 and sum the
ignored items to the ignoreditems column
if ocardtype is Paypal or Sofort, then just do the numitems sum
without checking the odate because those types require no odate
in another table called booked i have a column called ignoredoid,
this columns contains orderids from the above table that i want to
ignore even if the 3 conditions above are satsfied
To this point the query is working perfectly thanks to #Richard aka cyberkiwi to his answer in this question
The Question is, i need the result datatable to look like the following
+-----------+----------+--------------+-------------------+
| catalogid | numitems | ignoreditems | orderidcollection |
+-----------+----------+--------------+-------------------+
| 353 | 4 | 0 | O737,O739 |
| 364 | 10 | 0 | O738,O740 |
| 882 | 2 | 0 | O741 |
| 224 | 0 | 7 | |'O742 & O743 are ignored
+-----------+----------+--------------+-------------------+
as you can see the only change is the addition of orderidcollection column, it have to add the orderid to the new column seperated by a comma only if that order is not ignored in the code, i've been googling for couple hours with no luck!
is this even possible with SQL?
My Linq-to-Sql answer to your previous question extended to this one (LINQpad query):
Dim odateRequired = {"MasterCard", "Visa"}
Dim odateNotRequired = {"Paypal", "Sofort"}
Dim result = From o In Orders Join i In Oitems On o.orderid Equals i.orderid _
Let check = Not (From b In Bookeds Where b.ignoredoid=i.orderid).Any _
AndAlso o.ocardtype IsNot Nothing _
AndAlso ((odateRequired.Contains(o.ocardtype) AndAlso o.odate IsNot Nothing) _
OrElse odateNotRequired.Contains(o.ocardtype)) _
Group By i.catalogid Into _
numitems = Sum(If(check, i.numitems, 0)), _
ignoreditems = Sum(If(check, 0, i.numitems)), _
group
Select catalogid, numitems, ignoreditems, _
orderidcollection = String.Join(",", (From g in group Where g.check Select g.i.orderid))
result.Dump
Note this solution issues multiple SQL queries to determine the orderids for each catalogid where check is True to accumulate each orderidcollection. There may be a more efficient solution (either using some, probably convoluted, Linq-to-Sql that causes the generated SQL to do the equivalent of String.Join, or get the catalogid, numitems, check, orderid using Linq-to-Sql and then use Linq-to-objects to do the final accumulations).
Note also this query includes your Booked table (with LINQpad's pluralisation).

How to initialize a multidimensional array in VB.NET

I am trying to initialize a multidimensional array. Here is my syntax; this does not create errors but it does not store all values either. Although it correctly prints out all records in this snippet,
dFirstWeek = CDate(FirstWeek)
dFirstWeek = DateAdd(DateInterval.WeekOfYear, -1, dFirstWeek)
Dim dFirstDay As Date
Dim arrWeekYear(5000, 1) As Date
Dim i As Integer = 0
Dim j As Integer = 0
dFirstDay = dFirstDay.AddDays(1)
While dFirstWeek <= dLastWeek
dFirstDay = dFirstWeek
dFirstWeek = dFirstWeek.AddDays(7)
While dFirstDay < dFirstWeek
arrWeekYear(i, j) = (dFirstWeek)
arrWeekYear(i, j + 1) = (dFirstDay)
Response.Write(arrWeekYear(i, j).ToString("d"))
Response.Write(" ;")
Response.Write(arrWeekYear(i, j + 1).ToString("d"))
Response.Write("<br>")
dFirstDay = dFirstDay.AddDays(1)
j = 0
End While
i = i + 1
End While
later in this code, I try to reprint this array as follows:
i = 0
j = 0
Dim k As Integer = 0
'Response.Write(arrWeekYear.GetLength(0))
While k < arrWeekYear.GetLength(0) - 2
Response.Write(arrWeekYear(i, j).ToString("d"))
Response.Write(" ;")
Response.Write(arrWeekYear(i, j + 1).ToString("d"))
Response.Write("<br>")
j = 0
i = i + 1
k = k + 1
End While
but this time, only one "j" record appears per "i" record. Why is this? And then after these few records, many dates resembling null dates appear: "1/1/0001 "
So why do all records appear in upper section, but not from lower? Did I insert values wrongly into this array? And it does not have to have fixed number of rows, just a fixed number of columns.
Dim arrWeekYear(5000, 1) As Date
That’s a multi-dimensional array all right, but the second dimension only has a size of 2! And you access it via j, which is always 0 in your code. That makes no sense. Is that really what you want? I suggest you use a data structure inside your array instead of a multi-dimensional array.
In fact, you almost never want to use a multi-dimensional array. At all. Complex objects are almost always more appropriate. The only real exception is when you actually want to store a mathematical matrix.
Increment i inside the inner loop, rather than inside the outer loop.
And even simpler code (requires visual studio 2010):
Dim baseDate As Datetime = Convert.ToDatetime(FirstWeek).AddDays(-7)
For Each item In Enumerable.Range(0, (dLastWeek - baseDate).TotalDays / 7) _
.Select(Function(i) New DateTime() _
{baseDate.AddDays(i*7), baseDate.AddDays(i*7 + 7) })
Response.Write(string.Format("{0:d} ;{1:d}<br/>", item(0), item(1)))
Next item
And since Response.Write() is frowned upon in asp.net, you can take this a step further and assign the Enumerable.Range() call as the datasource for an asp:repeater control, if you're using webforms rather than mvc.
In the first piece you fill the array writing 7 times a value in the same array line.
In a test (from 01/01/2011 to 03/03/2011) the first 21 assignments are:
i | j | value | j+1 | value
0 | 0 | 01/01/2011 | 1 | 25/12/2010
0 | 0 | 01/01/2011 | 1 | 26/12/2010
0 | 0 | 01/01/2011 | 1 | 27/12/2010
0 | 0 | 01/01/2011 | 1 | 28/12/2010
0 | 0 | 01/01/2011 | 1 | 29/12/2010
0 | 0 | 01/01/2011 | 1 | 30/12/2010
0 | 0 | 01/01/2011 | 1 | 31/12/2010 final value in array (0,0) and (0,1)
1 | 0 | 08/01/2011 | 1 | 01/01/2011
1 | 0 | 08/01/2011 | 1 | 02/01/2011
1 | 0 | 08/01/2011 | 1 | 03/01/2011
1 | 0 | 08/01/2011 | 1 | 04/01/2011
1 | 0 | 08/01/2011 | 1 | 05/01/2011
1 | 0 | 08/01/2011 | 1 | 06/01/2011
1 | 0 | 08/01/2011 | 1 | 07/01/2011 final value in array (1,0) and 1,1)
2 | 0 | 15/01/2011 | 1 | 08/01/2011
2 | 0 | 15/01/2011 | 1 | 09/01/2011
2 | 0 | 15/01/2011 | 1 | 10/01/2011
2 | 0 | 15/01/2011 | 1 | 11/01/2011
2 | 0 | 15/01/2011 | 1 | 12/01/2011
2 | 0 | 15/01/2011 | 1 | 13/01/2011
2 | 0 | 15/01/2011 | 1 | 14/01/2011 final value in array (2,0) and (2,1)
etc.
In the 2nd part you get the values written :
i | j | value | j+1 | value
0 | 0 | 01/01/2011 | 1 | 31/12/2010
1 | 0 | 08/01/2011 | 1 | 07/01/2011
2 | 0 | 15/01/2011 | 1 | 14/01/2011
3 | 0 | 22/01/2011 | 1 | 21/01/2011
4 | 0 | 29/01/2011 | 1 | 28/01/2011
5 | 0 | 05/02/2011 | 1 | 04/02/2011
6 | 0 | 12/02/2011 | 1 | 11/02/2011
7 | 0 | 19/02/2011 | 1 | 18/02/2011
8 | 0 | 26/02/2011 | 1 | 25/02/2011
9 | 0 | 05/03/2011 | 1 | 04/03/2011
10 | 0 | 01/01/0001 | 1 | 01/01/0001
and this is the value in the rest of the array.
I think you forgot to increment some value in part 1?!?

Keeping the value of a COUNTIF after removing duplicates (Excel 2007)

I have a spreadsheet with multiple duplicate rows. I need this data sorted in order of their frequency, so I setup a COUNTIF and sorted them. Now I would like to remove the duplicate rows, but keep the COUNTIF at the same value and have Excel add to it if other duplicates are added to the spreadsheet in the future.
How can I go about doing this?
EDIT:
This may make it a little more complex, but below is an example of the data as it is now (the last number denotes the number of occurances; with my COUNTIF):
123 | Yes | 2,901 | 4,243 | 5555 | John | 4
123 | Yes | 2,919 | 4,528 | 5555 | John | 4
123 | Yes | 2,901 | 4,243 | 5555 | John | 4
123 | Yes | 4,243 | 4,128 | 5555 | John | 4
111 | 80 | 2,919 | 4,452 | 2222 | Joe | 2
111 | 80 | 11,00 | 2,901 | 2222 | Joe | 2
And this is how I need it to be:
123 | Yes | 2,901 | 4,243 | 5555 | John | 4
111 | 80 | 2,919 | 4,452 | 2222 | Joe | 2
Notice that despite some of the values not being an exact match the first cells (column A) are the same.
Hope that makes it a little more clear.
In case anyone is interested, below is the solution to my problem.
Sub Count()
Dim sID As String
Dim sOldID As String
Dim lLastRow As Long
Dim lrow As Long
Dim lcount As Long
lLastRow = ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
lrow = 2
sID = ActiveSheet.Cells(lrow, 1).Value
sOldID = ActiveSheet.Cells(1, 1).Value
lcount = 1
Do While Len(sID) <> 0
If sID <> sOldID Then
ActiveSheet.Cells(lrow - 1, 19).Value = lcount
sOldID = sID
lcount = 1
lrow = lrow + 1
Else
lcount = lcount + 1
ActiveSheet.Rows(lrow).Select
Selection.Delete Shift:=xlUp
End If
sID = ActiveSheet.Cells(lrow, 1).Value
Loop
ActiveSheet.Cells(lrow - 1, 19).Value = lcount
End Sub