返回列表 上一主題 發帖

[發問] 保留沒有重複的欄位

本帖最後由 luhpro 於 2020-12-3 04:55 編輯
如圖片所示,我想達到右邊表格的效果
(紅色是我故意標的,表示那是該序號內唯一的值)
不同序號要做區 ...
ssooi 發表於 2020-12-3 00:17

要篩選列出沒有重複(反之亦可)的資料,
使用Dictionary函數就可以了:
  1. Sub aa()
  2.   Dim iI%
  3.   Dim lRow&
  4.   Dim sStr$
  5.   Dim vD1, vD2, vA
  6.   
  7.   lRow = Cells(Rows.Count, 5).End(xlUp).Row
  8.   If lRow < 2 Then lRow = 2
  9.   Range([E2], Cells(lRow, 7)).Clear ' 清舊資料
  10.   Set vD1 = CreateObject("Scripting.Dictionary") ' 放重複次數
  11.   Set vD2 = CreateObject("Scripting.Dictionary") ' 放資料列號
  12.   lRow = 2
  13.   Do While Cells(lRow, 1) <> ""
  14.     sStr = Cells(lRow, 1) & "_" & Cells(lRow, 3) ' "_" 資料區隔符號,可改成資料中不會出現的特定字元
  15.     If IsEmpty(vD1(sStr)) Then
  16.       vD1(sStr) = 1
  17.       vD2(sStr) = lRow
  18.     Else
  19.       vD1(sStr) = vD1(sStr) + 1
  20.     End If
  21.     lRow = lRow + 1
  22.   Loop
  23.   
  24.   lRow = 2
  25.   For Each vA In vD1.keys
  26.     If vD1(vA) = 1 Then ' 重複次數為1的才列出來
  27.       For iI = 1 To 3
  28.         Cells(lRow, 4 + iI) = Cells(vD2(vA), iI)
  29.       Next
  30.       lRow = lRow + 1
  31.     End If
  32.   Next
  33. End Sub
複製代碼

保留沒有重複的欄位-Q1.zip (14.16 KB)

TOP

本帖最後由 luhpro 於 2020-12-3 20:41 編輯
回復  ssooi

...
For i = 2 To UBound(Arr)
    T = Arr(i, 1) & "_" & Arr(i, 3)
  1.     If xD(T) > 1 Then GoTo 100
  2.     N = N + 1
  3.     For j = 1 To 3: Arr(N + 1, j) = Arr(i, j): Next
  4. 100: Next
複製代碼
...
samwang 發表於 2020-12-3 13:55

以結構化程式的概念來說,
會建議儘量不要使用 Goto指令.
上述這段程式可以修改成: (單純轉換成等效指令, 並未驗證你的程式執行結果)
  1.     If xD(T) = 1 Then
  2.         N = N + 1
  3.         For j = 1 To 3: Arr(N + 1, j) = Arr(i, j): Next
  4.     End if
  5. Next
複製代碼
效果應該是相同的,
上述僅供參考...

TOP

謝謝大家
太感動了
luhpro 大大的程式我一開始就有試過
是完全沒問題的
只是他的程式太難~我無法消化
...
ssooi 發表於 2020-12-3 20:54

太難...... O.O
我(業餘者)的程式大都是陽春型的,
很少牽扯到簡化程式碼的部分呢.

要了解程式怎麼跑的,
有個滿不錯的功能:檢視->區域變數視窗,
善用單步模式(F8)
並把左邊有+的都點一下打開觀察每個指令對其成員及內含值的變化,
再搭配底下 即時運算視窗 用 ?變數名 來取值做確認.

Dictionary 不是太難的東西,
它有兩個部分 Item 與 key
Item=vD(key) ' 內含值 = vD(鍵值)

Cells 則是 儲存格的表示形式之一,
Range("B5")=Cells(5, 2) ' Range("儲存格位址")=Cells(列號, 欄號)

IsEmpty 函數則是檢查括弧內的值是否為空,
希望對你有所幫助.

TOP

回復  luhpro


我習慣用 GOTO , 它可簡化或減少些判斷,
例如:
IF A=1 AND B=2 AND C=3 THEN
  執行 ...
准提部林 發表於 2020-12-4 17:23

以你所舉的例子在結構化程式會是這樣的形式:
  For ...
    If A<>1 Then  '這條件成立, 跳至下個迴圈, 而不須再進行B及C的判斷
      If B<>2 Then
        If C<>3 Then
          ......
       End If
     End If
   End If  
...
  Next

程式寫法, 大家都會養成個人習慣, 只要不影響程式運行效率, 大都能接受吧!!!

嗯......
是的, 使用適合自己的方式就可以了.

TOP

本帖最後由 luhpro 於 2020-12-8 01:58 編輯

回復 15# n7822123
一般經歷過5.25"磁碟片的人應該也都知道組合語言吧.(總覺得那些遊戲程式又小又超好玩的)
還記得那時侯瘋狂的買組合語言和Basic的書邊看邊學,(一台PC要7萬多,那時還看不到中文呢)
但我也只能算是解析過知道位元移位是甚麼概念罷了,
真要說程式設計還是有很多要學的,
這網站上可挖的寶太多了,學不完阿......

Goto 當然是最早期的基本指令.
它的應用彈性與範圍非常大,
卻也容易因為非預期運算子帶入邏輯條件而走入誤區,
所以後來高階語言才會設計出專有的迴圈指令.

像我一般都是先打好外圍成對指令再在裡面加指令, 即:
先打 Do ... While  或是 For...Next 亦或是 With...End With等,
再在中間加上指令,
好處是作用範圍不會錯,
也不會發生對應不到或不小心交錯成對指令(例 :  For ...  For...  Next...  Next)的情形.

結構化程式是較易解析判讀對想學習的人也較適合.
當然,各種方式與指令只要能善用都是很好的.

你的例子用 Do...Loop Until 迴圈就可以完成的喔:
  1. Do
  2.   I = I + 1
  3.   S = S + I
  4. Loop Until Not (I < N)
複製代碼
當然, While...Wend 迴圈也是沒問題的:
  1. While I < N
  2.   I = I + 1
  3.   S = S + I
  4. Wend
複製代碼

TOP

        靜思自在 : 唯其尊重自己的人,才更勇於縮小自己。
返回列表 上一主題