Board logo

標題: [發問] 比較一堆資料中規則問題,能否判讀 [打印本頁]

作者: boblovejoyce    時間: 2016-3-4 17:45     標題: 比較一堆資料中規則問題,能否判讀

請問各位大大~
資料非常大,但目前只想確認如下面狀態,該如何去判斷需求呢?有大大可以幫忙看一下嗎?


在開始和結束,這區間內
若以(NET DGND
可以去判斷這個區間的結果,有無符合需求?

需求1:
若區間內,只出現一次portRef則判斷(net DGND這個開始,是異常的
並且列表於儲存格中A列中

需求2:
若區間內,portRef出現多次,若有GND和VDD這兩種字眼,這樣也算是異常
並且列表於儲存格中A列中

--------------------------------------
(net DGND
              (joined
                (portRef DGND)
                (portRef GND
                  (instanceRef INS55717393))
                (portRef VDD
                  (instanceRef INS55717393)))
              (figure WIRE
                (path
                  (pointList
                    (pt 610 -380)
                    (pt 600 -380)
                    (pt 600 -400))))
              (figure WIRE
                (path
                  (pointList
                    (pt 760 -320)
                    (pt 740 -320)))))

[attach]23381[/attach][attach]23381[/attach]
作者: 准提部林    時間: 2016-3-5 17:55

上傳部份資料內容檔案, 並模擬幾個異常範例~~
作者: boblovejoyce    時間: 2016-3-7 08:23

回復 2# 准提部林

謝謝板主提醒
附上文字檔~目前是想要針對這文字檔,做資料分析
因為(net DGND   ;這種開頭的資料很多筆,在下一筆( net XXX)之前,會提取出下面的狀態,




[attach]23396[/attach]
作者: boblovejoyce    時間: 2016-3-7 08:27

回復 3# boblovejoyce

異常1:
若區間內,只出現一次portRef則判斷(net DGND這個開始,是異常的
這邊強調的是只出現一次portRef
那就會將 DGND 顯示到A列中
於是就繼續掃描下一個(net
異常2:
若區間內,portRef出現多次,若有GND和VDD這兩種字眼,這樣也算是異常
並且列表於儲存格中A列中
目的是不想要GND和VDD 同時出現在同一個 (net 區間內

板主可指教一下嗎?
作者: 准提部林    時間: 2016-3-7 21:42

本帖最後由 准提部林 於 2016-3-7 21:45 編輯

回復 4# boblovejoyce


(net DGND 為開頭, 可判斷
(pt 740 -320))))) 為結尾, 相似的很多, 這就無固定規則可判斷!
尚且文字檔只能找到一個net DGND, 而excel想表現的結果也未模擬!!!
作者: stillfish00    時間: 2016-3-8 11:09

回復 1# boblovejoyce
草草完成如下程式,
因為VB的正則表達式功能弱了點
所以又自己寫了 FindCloseBracket 找出匹配的右括號位置
  1. Sub Test()
  2.     Dim fn As Integer, allText As String, indexClose As Long
  3.     Dim fname
  4.     fname = Application.GetOpenFilename()
  5.     If TypeName(fname) = "Boolean" Then Exit Sub
  6.     fn = FreeFile()
  7.     Open fname For Input As #fn
  8.     allText = Input$(LOF(1), 1)
  9.     Close #fn
  10.    
  11.     Sheets.Add
  12.     Cells(1, 1).Resize(, 3) = Array("net", "check", "portRef")
  13.     Dim oRegex As Object: Set oRegex = CreateObject("vbscript.regexp")
  14.     Dim oMch As Object, oMch2 As Object, x, i As Long, j As Long, endindex As Long
  15.     Dim hasVDD As Boolean, hasGND As Boolean
  16.     With oRegex
  17.         .Global = True
  18.         .Pattern = "\(net\s+([^\s()]*)"     '(net 開頭,捕捉下一個非空白或()的字組
  19.         Set oMch = .Execute(allText)
  20.         
  21.         .Pattern = "\(portRef\s+([^\s()]*)"     '(portRef 開頭,捕捉下一個非空白或()的字組
  22.         i = 2
  23.         For Each x In oMch
  24.             endindex = FindCloseBracket(allText, x.firstIndex)
  25.             Set oMch2 = .Execute(Mid(allText, x.firstIndex, endindex - x.firstIndex + 1))
  26.             Cells(i, 1) = x.subMatches(0)
  27.             j = 3
  28.             hasVDD = False: hasGND = False
  29.             For Each y In oMch2
  30.                 If InStr(1, y.subMatches(0), "VDD", vbTextCompare) Then hasVDD = True
  31.                 If InStr(1, y.subMatches(0), "GND", vbTextCompare) Then hasGND = True
  32.                 Cells(i, j) = y.subMatches(0)
  33.                 j = j + 1
  34.             Next
  35.             Cells(i, 2) = IIf(oMch2.Count < 2 Or (hasVDD And hasGND), "X", "O")
  36.             
  37.             i = i + 1
  38.         Next
  39.     End With
  40. End Sub

  41. '   s: input string
  42. '   i: index of begin bracket "("
  43. Function FindCloseBracket(ByRef s As String, ByVal i As Long) As Long
  44.     Dim isInString As Boolean   'ex : 預防雙引號字串內的 () 誤判
  45.     i = i + 1   '從下一個字元開始
  46.     Do While i <= Len(s)
  47.         Select Case Mid(s, i, 1)
  48.         Case "("
  49.             If Not isInString Then
  50.                 i = FindCloseBracket(s, i)
  51.                 If i = 0 Then Exit Do
  52.             End If
  53.         Case ")"
  54.             If Not isInString Then
  55.                 FindCloseBracket = i
  56.                 Exit Function
  57.             End If
  58.         Case """"
  59.             isInString = Not isInString
  60.         Case Else
  61.         End Select
  62.         
  63.         i = i + 1
  64.         DoEvents
  65.     Loop
  66.     FindCloseBracket = 0
  67. End Function
複製代碼

作者: 准提部林    時間: 2016-3-8 21:51

只用簡單的規則,
(net DGND 表示開頭,
遇5個右括號 ))))) 為結尾,
若非此規則,不須再參考以下內容!

將文字檔貼至A欄,檢測有異常,在B欄以文字表示:
Sub TEST()
Dim xR As Range, T$, xH As Range, Cx
[B:B].ClearContents
For Each xR In Range([A1], Cells(Rows.Count, 1).End(xlUp))
  T = Trim(xR)
  If T = "(net DGND" Then Set xH = xR: ReDim Cx(3): GoTo 101
  If xH Is Nothing Then GoTo 101
  If InStr(xR, "portRef") Then Cx(0) = Cx(0) + 1
  If T = "(portRef GND" Then Cx(1) = 1: GoTo 101
  If T = "(portRef VDD" Then Cx(2) = 1: GoTo 101
  If Right(T, 5) = ")))))" Then
    If Val(Cx(0)) < 2 Then Cx(3) = 1
    If Cx(1) + Cx(2) > 1 Then Cx(3) = 2
    If Cx(3) > 0 Then Range(xH(1, 2), xR(1, 2)) = "異常(" & Cx(3) & ")"
    Set xH = Nothing
  End If
101: Next
End Sub

參考檔:
http://www.funp.net/634979
作者: boblovejoyce    時間: 2016-3-9 17:46

回復 6# stillfish00
謝謝回覆~可以處理
雖然我有試過數量行數很多時,我跑了一個小時~它才再繼續check和寫入
因為我的資料數量可以達到50萬行以上
然後又有重重的關係~~
如果有CHECK OK的,不需要寫入顯示出來,應該就會快些
作者: boblovejoyce    時間: 2016-3-9 17:52

回復 7# 准提部林


    謝謝回覆~
因為規則很多,這只是其中一個規則
我的規則,是在掃描只要有(net
就開始去判斷~
結尾不一定是)))))
結尾應該算是下一個(net之前~

我測試了~在這個固定的規則下,是OK的 (可是我有將CX(0)改成小於3)
逐行執行時,CX(1) CX(2) 始終沒有值
請教為什麼會沒有值?
作者: boblovejoyce    時間: 2016-3-10 08:37

回復 9# boblovejoyce

喔~把這個改成InStr,就有值了~
If InStr(T, "(portRef GND") > 0 Then Cx(1) = 1: GoTo 101
If InStr(T, "(portRef VDD") > 0 Then Cx(2) = 1: GoTo 101

謝謝
作者: stillfish00    時間: 2016-3-10 09:37

回復 8# boblovejoyce
資料那麼多筆要先講,上傳的檔案才兩筆就沒有優化了
  1. Sub Test()   
  2.     '== Read File ==
  3.     Dim fn As Integer, allText As String
  4.     Dim fname
  5.     fname = Application.GetOpenFilename()
  6.     If TypeName(fname) = "Boolean" Then Exit Sub
  7.     fn = FreeFile()
  8.     Open fname For Input As #fn
  9.     allText = Input$(LOF(1), 1)
  10.     Close #fn
  11.         
  12.     '== Parse Element ==
  13.     Dim oRegex As Object: Set oRegex = CreateObject("vbscript.regexp")
  14.     Dim oDic As Object: Set oDic = CreateObject("scripting.dictionary")
  15.     Dim oMch As Object, oMch2 As Object, x, i As Long, j As Long, endIndex As Long
  16.     Dim hasVDD As Boolean, hasGND As Boolean
  17.     With oRegex
  18.         .Global = True
  19.         .Pattern = "\(net\s+([^\s()]*)"     '(net 開頭,捕捉下一個非空白或()的字組
  20.         Set oMch = .Execute(allText)
  21.         
  22.         .Pattern = "\(portRef\s+([^\s()]*)"     '(portRef 開頭,捕捉下一個非空白或()的字組
  23.         i = 1
  24.         For Each x In oMch
  25.             endIndex = FindCloseBracket(allText, x.firstIndex)
  26.             If endIndex = 0 Then MsgBox "Fail to parse: " & vbNewLine & Mid(allText, x.firstIndex, 50) & "...": Exit Sub
  27.             Set oMch2 = .Execute(Mid(allText, x.firstIndex, endIndex - x.firstIndex + 1))
  28.             
  29.             hasVDD = False: hasGND = False
  30.             For Each y In oMch2
  31.                 If InStr(1, y.subMatches(0), "VDD", vbTextCompare) Then hasVDD = True
  32.                 If InStr(1, y.subMatches(0), "GND", vbTextCompare) Then hasGND = True
  33.             Next
  34.             
  35.             If oMch2.Count < 2 Or (hasVDD And hasGND) Then  'portRef低於兩個或同時含VDD及GND字串
  36.                 oDic.Add i, x.subMatches(0)
  37.                 i = i + 1
  38.             End If
  39.         Next
  40.     End With
  41.    
  42.     '== Output result ==
  43.     Dim ar
  44.     If oDic.Count = 0 Then MsgBox "All pass": Exit Sub
  45.     ar = oDic.items
  46.     With Sheets.Add
  47.         Application.ScreenUpdating = False
  48.         .[a1].Resize(UBound(ar) - LBound(ar) + 1) = OneDtoTwoD(ar)
  49.         Application.ScreenUpdating = True
  50.     End With
  51. End Sub

  52. '   s: input string
  53. '   i: index of begin bracket "("
  54. Function FindCloseBracket(ByRef s As String, ByVal i As Long) As Long
  55.     Dim isInString As Boolean   'ex : 預防雙引號字串內的 () 誤判
  56.     i = i + 1   '從下一個字元開始
  57.     Do While i <= Len(s)
  58.         Select Case Mid(s, i, 1)
  59.         Case "("
  60.             If Not isInString Then
  61.                 i = FindCloseBracket(s, i)
  62.                 If i = 0 Then Exit Do
  63.             End If
  64.         Case ")"
  65.             If Not isInString Then
  66.                 FindCloseBracket = i
  67.                 Exit Function
  68.             End If
  69.         Case """"
  70.             isInString = Not isInString
  71.         Case Else
  72.         End Select
  73.         i = i + 1
  74.     Loop
  75.     FindCloseBracket = 0
  76. End Function

  77. Function OneDtoTwoD(ar, Optional base As Integer) As Variant    'transepose array of elements > 65535
  78.     Dim i, retn()
  79.     ReDim retn(base To base + UBound(ar) - LBound(ar), base To base)  ' transe to base
  80.     For i = LBound(ar) To UBound(ar)
  81.         retn(i - LBound(ar) + base, base) = ar(i)
  82.     Next
  83.     OneDtoTwoD = retn
  84. End Function
複製代碼

作者: boblovejoyce    時間: 2016-3-11 15:21

回復 11# stillfish00

謝謝大大的回覆~
目前不解的是,為何跑完後,會有這幾個項次?
附上我的讀取檔案
[attach]23423[/attach]
&10104
&10306
&10208
&10205
&10108
&10314
&10414
&10102
&10311
&10204
&10115
作者: stillfish00    時間: 2016-3-11 19:39

本帖最後由 stillfish00 於 2016-3-11 19:42 編輯

回復 12# boblovejoyce
恩,firstIndex 這邊我錯了,match到第一個字時 firstIndex = 0,和VBA不一樣,難怪跑那麼久,修改如下

然後有些rename的我不知要取哪個名稱,都寫到第一欄
  1. Sub Test()
  2.     '== Read File ==
  3.     Dim fn As Integer, allText As String
  4.     Dim fname
  5.     fname = Application.GetOpenFilename()
  6.     If TypeName(fname) = "Boolean" Then Exit Sub
  7.     fn = FreeFile()
  8.     Open fname For Input As #fn
  9.     allText = Input$(LOF(1), 1)
  10.     Close #fn
  11.         
  12.     '== Parse Element ==
  13.     Dim oRegex As Object: Set oRegex = CreateObject("vbscript.regexp")
  14.     Dim oDic As Object: Set oDic = CreateObject("scripting.dictionary")
  15.     Dim omch As Object, oMch2 As Object, x, i As Long, j As Long, endIndex As Long
  16.     Dim hasVDD As Boolean, hasGND As Boolean
  17.     With oRegex
  18.         .Global = True
  19.         .Pattern = "\(net\s+(\(rename.*\)|[^\s()]*)"     '(net 開頭,捕捉下一個非空白或()的字組或rename...
  20.         Set omch = .Execute(allText)
  21.         
  22.         .Pattern = "\(portRef\s+([^\s()]*)"     '(portRef 開頭,捕捉下一個非空白或()的字組
  23.         i = 1
  24.         For Each x In omch
  25.             endIndex = FindCloseBracket(allText, x.firstIndex + 1)
  26.             If endIndex = 0 Then MsgBox "Fail to parse: " & vbNewLine & Mid(allText, (x.firstIndex + 1), 50) & "...": Exit Sub
  27.             Set oMch2 = .Execute(Mid(allText, x.firstIndex + 1, endIndex - (x.firstIndex + 1) + 1))
  28.             
  29.             hasVDD = False: hasGND = False
  30.             For Each y In oMch2
  31.                 If InStr(1, y.subMatches(0), "VDD", vbTextCompare) Then hasVDD = True
  32.                 If InStr(1, y.subMatches(0), "GND", vbTextCompare) Then hasGND = True
  33.             Next
  34.             
  35.             If oMch2.Count < 2 Or (hasVDD And hasGND) Then  'portRef低於兩個或同時含VDD及GND字串
  36.                 oDic.Add i, x.subMatches(0)
  37.                 i = i + 1
  38.             End If
  39.         Next
  40.     End With
  41.    
  42.     '== Output result ==
  43.     Dim ar
  44.     If oDic.Count = 0 Then MsgBox "All pass": Exit Sub
  45.     ar = oDic.items
  46.     With Sheets.Add
  47.         Application.ScreenUpdating = False
  48.         .[a1].Resize(UBound(ar) - LBound(ar) + 1) = OneDtoTwoD(ar)
  49.         Application.ScreenUpdating = True
  50.     End With
  51. End Sub

  52. '   s: input string
  53. '   i: index of begin bracket "("
  54. Function FindCloseBracket(ByRef s As String, ByVal i As Long) As Long
  55.     Dim isInString As Boolean   'ex : 預防雙引號字串內的 () 誤判
  56.     i = i + 1   '從下一個字元開始
  57.     Do While i <= Len(s)
  58.         Select Case Mid(s, i, 1)
  59.         Case "("
  60.             If Not isInString Then
  61.                 i = FindCloseBracket(s, i)
  62.                 If i = 0 Then Exit Do
  63.             End If
  64.         Case ")"
  65.             If Not isInString Then
  66.                 FindCloseBracket = i
  67.                 Exit Function
  68.             End If
  69.         Case """"
  70.             isInString = Not isInString
  71.         Case Else
  72.         End Select
  73.         i = i + 1
  74.     Loop
  75.     FindCloseBracket = 0
  76. End Function

  77. Function OneDtoTwoD(ar, Optional base As Integer) As Variant    'transepose array of elements > 65535
  78.     Dim i, retn()
  79.     ReDim retn(base To base + UBound(ar) - LBound(ar), base To base)  ' transe to base
  80.     For i = LBound(ar) To UBound(ar)
  81.         retn(i - LBound(ar) + base, base) = ar(i)
  82.     Next
  83.     OneDtoTwoD = retn
  84. End Function
複製代碼

作者: boblovejoyce    時間: 2016-3-14 11:27

回復 13# stillfish00
謝謝大大~調整
測試後,正常又快速~:)




歡迎光臨 麻辣家族討論版版 (http://forum.twbts.com/)