【问题标题】:Tracking No Or Auto No For Entries With The Same Product Id and Invoice对于具有相同产品 ID 和发票的条目,跟踪否或自动否
【发布时间】:2017-12-29 00:00:11
【问题描述】:

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

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 表,产品 id 101 有两个条目具有相同的发票编号,但时间和数量不同。我想要的是在有类似的发票编号和产品 ID(重复发票编号和产品 ID)时创建一个跟踪编号。假设对于产品 ID 101,它已经有两个条目,发票编号为“Inv-1000”。所以它应该在数据库表中创建两个不同的跟踪,如下所示 1 和 2:

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 表列与表格列不匹配,则不允许上传数据。同样,我尝试验证 excel 工作表的行数据。在这种情况下,如果产品 ID 为 101,发票编号为 'Inv-1000' 已经在表格中,并且即使已经存在像 1、2 这样的不同跟踪,那么它不应该允许进一步上传此数据。它看起来很简单,但没有开始工作。挣扎!示例 - 存在于表中:

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

【问题讨论】:

  • 更新了我的答案,请看一下。顺便说一句,你的意思是真正的发票,每年都是唯一的吗?
  • 是的,应该是这样。如果你有时间,看看这个 - stackoverflow.com/questions/45390202/…

标签: sql-server vb6 sql-server-2000


【解决方案1】:

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

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

编辑:

此外,在我看来,您的 sn-p 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") 中找到结果。这里不需要循环记录。您应该在每次插入后重新查询此记录集。

EDIT2: 这是一个未经测试的伪代码sn-p,你应该明白了:

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

恕我直言,如果您在表格中存储本机数据类型而不是所有文本值会更好,那么您可能还需要在此处检查 Excel 单元格 的数据类型并提供正确的根据目标表的类型进行转换。 抱歉,但我认为数据类型转换的主题过于宽泛,不适合在这里 - 您最好为此发布一些新问题。

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

EDIT3:

如果基于上述 sn-p 的导入已经过测试并且可以正常工作,则可以使用 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

如果您的数据有足够的时间分辨率,我相信您可以跳过相同数量的检查,这取决于您,但无论如何,您应该调查 Excel 文件中“发票日期”字段的内容。

【讨论】:

  • 看起来很有希望@deblocker。如果您可以使用 excel 文件提供示例示例,那将非常有帮助。
  • Excel 文件的内容无关紧要,产品 ID 也无关紧要。每次您需要在表中插入新记录时,您应该按发票编号和发票日期过滤该表,如下所示:SELECT MAX ([Auto No]) FROM ExcelData WHERE [Invoice No]= 'Inv-1000' AND [Invoice Date] = 7/10/2017。注意你如何比较日期。您应该增加该结果(在您的情况下,您选择 +1)。
  • 你调查过表的主键吗?应为发票编号、发票日期、自动编号。另外,请确保自动编号未设置为身份。
  • Auto No 未设置为身份@deblocker。您的查询非常完美。但我的问题是:我的 excel 表一次有很多数据,并使用表单加载它们。在您的查询中,我怎么能适应这个 - SELECT ISNULL(MAX([Auto No]),0) FROM ExcelData WHERE [Invoice No] = 'Inv-1000' AND [Invoice Date] = 7/10/2017Requery 属性会起作用吗?
  • 非常感谢@deblocker。你是一个完美主义者。我感谢你的辛勤工作和时间。干杯!这是一堂很棒的课。
猜你喜欢
  • 2020-04-09
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多