对具有相同产品 ID 和发票的条目跟踪否或自动否

Tracking No Or Auto No For Entries With The Same Product Id and Invoice

我在尝试做一件简单的事情,让我先说清楚。我有一个 excel 文件,应用程序正在加载它以将 excel 数据存储在数据库 table 中。它工作正常并上传数据。现在我在这种情况下有一个要求,下面是 excel sheet:

ProductId - Invoice No - Invoice Date - Price - Quantity
101 - Inv-1000 - 7/10/2017 10:00 - 1000 - 10
101 - Inv-1000 - 7/10/2017 10:30 - 200 - 2
102 - Inv-1000 - 7/10/2017 10:30 - 400 - 20
101 - Inv-1001 - 7/11/2017 10:30 - 300 - 5
102 - Inv-1001 - 7/11/2017 10:30 - 200 - 5

在 excel sheet 中看到,产品 ID 101 有两个具有相同发票编号但时间和数量不同的条目。我想要的是在有类似的发票号和产品 ID(重复发票号和产品 ID)时创建一个跟踪号。假设,对于产品 ID 101,它已经有两个发票编号为 'Inv-1000' 的条目。所以它应该在数据库中创建两个不同的跟踪 1 和 2,如下所示 table:

ProductId - Invoice No - Invoice Date - Price - Quantity - Auto No
101 - Inv-1000 - 7/10/2017 10:00 - 1000 - 10 - 1
101 - Inv-1000 - 7/10/2017 10:30 - 200 - 2 - 2
102 - Inv-1000 - 7/10/2017 10:30 - 400 - 20 - 1
101 - Inv-1001 - 7/11/2017 10:30 - 300 - 5 - 1
102 - Inv-1001 - 7/11/2017 10:30 - 200 - 5 - 1

我尝试使用以下代码来完成上述任务,但它只为所有条目创建 1 个,即使是重复的条目也是如此:

Do Until rs3.EOF
  If (rs4.recordCount > 0) Then
     generateId = rs3.Fields.Item("Auto No") + 1
  Else
     generateId = 1
  End If           
rs3.MoveNext
Loop

我好像漏掉了什么。在这方面,任何想法或建议将不胜感激。谢谢。

注意:我现在正在验证列名,这意味着如果 excel sheet 列与 table 列不匹配,则不允许上传数据。同样,我尝试验证 excel sheet 的行数据。在这种情况下,如果产品 ID 101,发票编号 'Inv-1000' 已经在 table 中并且即使已经存在不同的跟踪(如 1、2),则不应允许进一步上传此数据。它看起来很简单,但不要开始工作。挣扎!示例 - 存在于 table:

ProductId - Invoice No - Invoice Date - Price - Quantity - Auto No
101 - Inv-1000 - 7/10/2017 10:00 - 1000 - 10 - 1
101 - Inv-1000 - 7/10/2017 10:30 - 200 - 2 - 2
102 - Inv-1000 - 7/10/2017 10:30 - 400 - 20 - 1
101 - Inv-1001 - 7/11/2017 10:30 - 300 - 5 - 1
102 - Inv-1001 - 7/11/2017 10:30 - 200 - 5 - 1

以上数据终于不允许在下次上传了。还有一点,将文件保存在D目录和TextBox中,写这个上传excel文件 - D:\SampleExcel.xlsx

完整代码:

Dim recordCount As Integer 'Variable to get record count
Dim i As Integer

Private Sub btnUpload_Click()
   LoadExcelSheet
End Sub


'**Method To Upload Excel File - Starts**
Public Sub LoadExcelSheet()
Dim con As ADODB.Connection
Dim conn As ADODB.Connection

'**Record Set To Check Table Records - Starts**
Dim rs As ADODB.Recordset
Dim rs2 As ADODB.Recordset
Dim rs3 As ADODB.Recordset
Dim rs4 As ADODB.Recordset
'**Record Set To Check Table Records - Ends**

Dim i As Long

Dim strQuery As String
Dim strQueryExistData As String
Dim strQueryMatchCol As String
Dim strQueryExcel As String

Dim strFile As String
Dim strSheet As String


Set con = New ADODB.Connection
Set conn = New ADODB.Connection

Set rs = New ADODB.Recordset
Set rs2 = New ADODB.Recordset
Set rs3 = New ADODB.Recordset
Set rs4 = New ADODB.Recordset

i = 0

strFile = txtFileName.Text
strSheet = "Sheet1"
con.Provider = "Microsoft.ACE.OLEDB.12.0"
con.ConnectionString = "Data Source = " & strFile & ";" & "Extended Properties = Excel 12.0;"

conn.Open "Provider=SQLOLEDB.1;Persist Security Info=False;Initial Catalog=Northwind;Data Source=.;"

con.Open

strQuery = "SELECT * FROM [" & strSheet & "$]"
strQueryMatchCol = "SELECT m.[ProductId], m.[Invoice No], m.[Invoice Date], m.[Price], m.[Quantity]  FROM ExcelData m"
strQueryExistData = "SELECT m.[ProductId], m.[Invoice No], m.[Auto No] FROM ExcelData m"
strQueryExcel = "SELECT [ProductId], [Invoice No] FROM [" & strSheet & "$]"

rs.Open strQuery, con, adOpenStatic, adLockOptimistic
rs2.Open strQueryMatchCol, conn, adOpenStatic, adLockOptimistic
rs3.Open strQueryExistData, conn, adOpenStatic, adLockOptimistic
rs4.Open strQueryExcel, con, adOpenStatic, adLockOptimistic

strDate = Format(Now, "YYYY-MM-DD") + " 00:00:00"

  Do Until rs.EOF

  Dim poNo As String
  Dim itemCode As String
  Dim grnNo As String
  Dim matDes As String
  Dim transName As String
  Dim goDown As String
  Dim vendorName As String
  Dim process As String
  Dim vendorDnNo As String
  Dim rcvQty As String
  Dim unit As String
  Dim totalAmt As String
  Dim invoiceNo As String
  Dim generateId As Integer

  generateId = 1

  '**Check Excel Column - Validation**
  If (rs.Fields(0).Name = rs2.Fields(0).Name And rs.Fields(1).Name = rs2.Fields(1).Name And rs.Fields(2).Name = rs2.Fields(2).Name And rs.Fields(3).Name = rs2.Fields(3).Name And rs.Fields(4).Name = rs2.Fields(4).Name And rs.Fields(0).Name <> "") Then

  '**Trying To Check If Product Has The Same Id and Invoice No, Then Increment By One Or Just One**
  '**Example - If Product Id 101 and Invoice No Inv-1000 Has Two Entries (Repeated), Then In The [Auto No] Column
  'Should Be Included With The Numbers 1 and 2**
  Do Until rs3.EOF
  If (rs4.recordCount > 0) Then
    generateId = rs3.Fields.Item("Auto No") + 1
  Else
    generateId = 1
  End If

  rs3.MoveNext
  Loop

  conn.Execute ("INSERT INTO ExcelData ([ProductId], [Invoice No], [Invoice Date], [Price], [Quantity], [Auto No]) VALUES ('" + Trim(rs.Fields(0).Value) + "', '" + Trim(rs.Fields(1).Value) + "', '" + Trim(rs.Fields(2).Value) + "', '" + Trim(rs.Fields(3).Value) + "', '" + Trim(rs.Fields(4).Value) + "', '" + Trim(generateId) + "')")

    i = 1

  Else

    i = 0

  End If

  rs.MoveNext

  Loop

  If (i = 0) Then
     MsgBox "Column names aren't in correct order! Please check excel sheet 1.", vbInformation, "Info"
  ElseIf (i = 1) Then
     MsgBox "Uploaded!", vbInformation, "Info"
  End If
rs.Close

Set rs = Nothing

con.Close
conn.Close

Set con = Nothing
Set conn = Nothing
End Sub
'**Method To Upload Excel File - Ends**

使用上面的代码,现在只能得到以下输出:

ProductId - Invoice No - Invoice Date - Price - Quantity - Auto No
101 - Inv-1000 - 7/10/2017 10:00 - 1000 - 10 - 1
101 - Inv-1000 - 7/10/2017 10:30 - 200 - 2 - 1
102 - Inv-1000 - 7/10/2017 10:30 - 400 - 20 - 1
101 - Inv-1001 - 7/11/2017 10:30 - 300 - 5 - 1
102 - Inv-1001 - 7/11/2017 10:30 - 200 - 5 - 1

您应该刷新 rs3 记录集的内容,以获取当前数据,从而获得更新的记录数,否则您将始终拥有打开它时的数据。

由于您正在使用模块级变量来存储记录数,因此在循环中,在 conn.Execute ("INSERT INTO.... 之后您可以简单地使用:rs3.requery。这在某种程度上等同于您在 INSERT INTO 语句之前关闭并重新打开 rs3 记录集。

编辑:

此外,在我看来,您的代码段 Do Until rs3.EOF... 应该替换为这样的查询:SELECT ISNULL(MAX([Auto No]),0) FROM ExcelData WHERE [Invoice No]= 'Inv-1000' AND YEAR([Invoice Date]) = 2017。您应该增加该结果。请注意你是如何比较日期的,对于这个选择查询,去掉时间部分。您会在 rs3.fields("Auto No") 中找到结果。这里不需要遍历记录。您应该在每次插入后重新查询此记录集。

编辑2: 这是一个未经测试的伪代码片段,你应该明白了:

fmtString = "YYYY-MM-DD hh:mm:ss" ' you should adapt this to your need '
rs.Open "SELECT * FROM [" & strSheet & "$]", con, adOpenForwardOnly
Do Until rs.EOF
  InvNo = Trim(rs.Fields("InvoiceNo").Value)
  InvDateTime = CDate(rs.Fields("Invoice Date").Value)
  ' separate year from full datetime, depending how the cell format is '
  InvYear = Format(InvDateTime, "YYYY")
  ' compose the query to get the Auto No '
  sql = "SELECT ISNULL(MAX([Auto No]),0) AS MaxNo FROM ExcelData"
  sql += " WHERE [Invoice No] = '" + InvNo + "' "
  sql += " AND YEAR([Invoice Date]) = '" + InvYear + "'"
  Set rsCheck = conn.Execute(sql) ' get the Auto No '
  AutoNo = rsCheck.Fields("MaxNo").Value + 1
  ' compose the query to store the invoices '
  sql = "INSERT INTO ExcelData ("
  sql += "ProductId, "
  sql += "[Invoice No], "
  sql += "[Invoice Date], "
  sql += "Price, "
  sql += "Quantity, "
  sql += "[Auto No]"
  sql += ") VALUES ("
  sql += "'" + Trim(rs.Fields("ProductId").Value) + "',"
  sql += "'" + InvNo + "',"
  sql += "'" + Format(InvDateTime, fmtString) + "',"
  sql += CCur(Trim(rs.Fields("Price").Value)) + ","
  sql += CSng(Trim(rs.Fields("Quantity").Value)) + ","
  sql += AutoNo 
  sql += ")"
  conn.Execute(sql) ' store the invoice '
  rs.MoveNext
Loop

恕我直言,如果您将本机数据类型存储在 table 而不是所有文本值中会更好,那么您可能还需要在此处检查 Excel cell 并针对目标 table 的 column 类型提供正确的转换。 抱歉,但我认为数据类型转换的主题过于宽泛,不适合放在这里 - 你最好 post 提出一些新问题。

如果您希望将所有值存储为文本以避免所有这些无聊的数据类型转换,我建议您以 YYYY-MM-DD HH:MM:SS 格式存储日期(24,否 AM/PM) 和固定长度格式 001..002..003 中的 AutoNo,因此它们至少被正确排序。

编辑3:

如果基于上述代码段的导入经过测试并正常工作,您可以使用 Excel 文件的确切日期时间重写对已导入行的检查,如下所示:

fmtString = "YYYY-MM-DD hh:mm:ss" ' you should adapt this to your need '
rs.Open "SELECT * FROM [" & strSheet & "$]", con, adOpenForwardOnly
Do Until rs.EOF
  InvNo = Trim(rs.Fields("InvoiceNo").Value)
  InvDateTime = CDate(rs.Fields("Invoice Date").Value)
  ProdId = Trim(rs.Fields("ProductId").Value)
  ' compose the query to get the same invoice line '
  sql = "SELECT COUNT(*) AS ThisLine FROM ExcelData"
  sql += " WHERE [Invoice No] = '" + InvNo + "' "
  sql += " AND [Invoice Date] = '" + Format(InvDateTime, fmtString) + "'"
  sql += " AND [ProductId] = '" + ProdId + "' "
  Set rsCheck = conn.Execute(sql) ' get the current line '
  If rsCheck.Fields("ThisLine").Value = 0 Then
    ' compose the query to get the Auto No '
    ...
    ...
    conn.Execute(sql) ' store the invoice '
  End If
  rs.MoveNext
Loop

如果您的数据有足够的时间分辨率,我相信您可以跳过相同数量的检查,由您决定,但无论如何,您应该调查 [=51= 中发票日期字段的内容] 文件)。