標題:
[發問]
如何使用VBA或函數做多個陣列數值的比較及格式化條件的設定
[打印本頁]
作者:
cmo140497
時間:
2012-12-16 22:09
標題:
如何使用VBA或函數做多個陣列數值的比較及格式化條件的設定
本帖最後由 GBKEE 於 2012-12-17 15:51 編輯
Dear 各位版主或高手大大們 :
小弟先前請教過各位版主及大大的一些巨集的問題,也感謝各位的不吝指教,今有一個問題,已經煩了快一個月,已遍歷國外各大網站vba或函數的例子,仍無法解決困擾已久的問題
希望可以從各位版主或高手大大們尋得協助,謝謝!
以下介紹幾個網站還滿不錯的:
http://www.get-digital-help.com/category/excel/table/
http://chandoo.org/wp/2009/03/25/using-array-formulas-example1/
http://www.contextures.com/tiptech.html
小弟想依指定路徑下之資料夾找到資料夾內之檔案,作自動新增核取方塊數量,如以下圖片有3個文字檔內容已被小弟載入excel內,要如何比較各筆之相同位址之資料,是否重覆?如有
重覆並計算重覆次數除以核定片數,作百分比之格式化條件的顏色分類,如下圖所示
[attach]13552[/attach]
[attach]13553[/attach]
作者:
Hsieh
時間:
2012-12-16 23:47
回復
1#
cmo140497
試試看
Sub AddCheckBox() '加入核取方塊
'因為沒有提供文字檔,以現有Item作為新增條件
With Sheet1
.CheckBoxes.Delete
k = Application.CountIf(.Columns("E"), "ID")
Set A = .Columns("F").Find("Item", lookat:=xlPart)
For i = 1 To k
With .CheckBoxes.Add(.Cells(i + 4, "C").Left, .Cells(i + 4, "C").Top, .Cells(i + 4, "C").Width, .Cells(i + 4, "C").Height)
.Characters.Text = A
End With
Set A = .Columns("F").FindNext(A)
Next
End With
End Sub
Sub 比對()
Dim Sp As Shape, Rng As Range, A As Range, MyRng As Range
With Sheet1
For Each Sp In .Shapes
If Sp.Name Like "Check Box*" Then
Set A = .Columns("F").Find(Sp.OLEFormat.Object.Caption)
If Sp.OLEFormat.Object.Value = 1 Then
If Rng Is Nothing Then
Set Rng = A.Offset(1, 0).Resize(5, 5)
Else
Set Rng = Union(Rng, A.Offset(1, 0).Resize(5, 5))
End If
End If
End If
Next
Set MyRng = .[M3:Q7]
If Not Rng Is Nothing Then
For i = 1 To 5
For j = 1 To 5
If MyRng(i, j) <> 0 And MyRng(i, j) <> "___" Then
For Each ar In Rng.Areas
If ar(i, j) = MyRng(i, j) Then p = p + 1
Next
s = p / Rng.Areas.Count: p = 0
n = Application.Lookup(s, Array(0, 0.1, 0.2, 0.4, 0.6, 0.8, 1), Array(1, 2, 3, 4, 5, 6, 7))
MyRng.Cells(i, j).Interior.ColorIndex = .[S2:Y2].Cells(1, n).Interior.ColorIndex
Else
MyRng.Cells(i, j).Interior.ColorIndex = -4142
End If
Next
Next
End If
End With
End Sub
複製代碼
作者:
cmo140497
時間:
2012-12-17 09:12
回復
2#
Hsieh
實在大大的感謝Hsieh 超級版主的頂力協助,請問版主您大概寫這個程式花了多少時間,小弟昨晚po的,才剛上班打開電腦就收到回覆了,實在令小弟有點....:'(
另還有一個問題想請教版主,關於底下這行,這陣列是小弟自己用算的,請問要如何自行做陣列之運算(比較/合併),將有重覆或獨立值代至新的陣列內,仍繼續做條件格式化百分比,
Set MyRng = .[M3:Q7]
因為這陣列有可能x/y會有20~50之多,如果可以自行比較出結果的話.....再度感謝版主不辭辛苦的解決新手小弟的困擾,實在感恩!
作者:
Hsieh
時間:
2012-12-17 09:19
回復 Hsieh
實在大大的感謝Hsieh 超級版主的頂力協助,請問版主您大概寫這個程式花了多少時間,小 ...
cmo140497 發表於 2012-12-17 09:12
用多少時間並不重要,是否達到需求才是重點
至於MyRng是要比對改變顏色的區域
至於你要多個範圍就看你的表格分佈規則而定
上傳檔案試試看吧
作者:
cmo140497
時間:
2012-12-17 09:31
回復
2#
Hsieh
不好意思,版主再度打擾您,剛才忘記附上文字檔.
如果各陣列位址的值均不相同,則視為100%,代碼7的顏色,不知是否可行,感謝您。
[attach]13555[/attach]
作者:
cmo140497
時間:
2012-12-17 09:47
回復
4#
Hsieh
不好意思,小弟沒來得及看回覆,又丟了疑問給您,實在抱歉.
小弟的陣列均為二維,行列數有時可能會多達20更甚多,內容只有固定之數值F00~F150,沒有其它數值或文字,只是陣列數須依實際檔案數而定,要篩選或比對則由人自行決定,
資料附檔如下附件,請參考,再度感謝,謝謝!
[attach]13556[/attach]
作者:
Hsieh
時間:
2012-12-17 10:32
回復
6#
cmo140497
這樣已經錯亂了,請說明你的整體流程
所附的txt檔案是要寫入E:J欄位或是要放到M:Q欄作為比對變色儲存格?
這些文字檔資料所形成的陣列欄、列數可能是不同的,那麼顏色對照表[S2:Y2]的位置是否又要改變?
作者:
cmo140497
時間:
2012-12-17 13:34
回復
7#
Hsieh
不好意思,小弟再整理一下流程,再麻煩版主您再幫小弟看一下,再度打擾您了,謝謝!
[attach]13575[/attach]
[attach]13576[/attach]
作者:
GBKEE
時間:
2012-12-17 15:42
回復
8#
cmo140497
AUTO_OPEN() 檔案開啟時自動執行
Option Explicit
Sub AUTO_OPEN() '加入核取方塊'因為沒有提供文字檔,以現有Item作為新增條件
Dim A As Range, K As Integer, i As Integer
With Sheet1
.CheckBoxes.Delete
.Range("B:Z").Interior.ColorIndex = xlNone
K = Application.CountIf(.Columns("A"), "ID")
Set A = .Columns("A").Find("ID", lookat:=xlPart)
For i = 1 To K
Cells(i + 5, "AA").Select
With .CheckBoxes.Add(.Cells(i + 5, "AA").Left, .Cells(i + 5, "AA").Top, .Cells(i + 5, "AA").Width, .Cells(i + 5, "AA").Height)
.Characters.Text = "Item" & i
.Name = "Item" & i
.OnAction = "EX" 'CheckBoxes 指巨集的 程式
End With
A.Offset(1, 1).Resize(24, 24).Name = "_Item" & i '資料範圍設立名稱:如工作表定義名稱
Set A = .Columns("A").FindNext(A)
Next
'** 製定百分比 為 7 等分 [S1:Y1] 百分比由大到小 ***
For i = 1 To 7 '百分比由大到小
.[AA2].Cells(1, i) = 1 + (1 / 7) - (i / 7)
Next
End With
End Sub
Sub EX() '已執行AUTO_OPEN, 按選CheckBoxes的程式
Dim Rng(0 To 25) As Range, S, i
Dim P As Integer, B As CheckBox, E As Variant
With Sheet1
.Range("B:Z").Interior.ColorIndex = xlNone
For Each B In .CheckBoxes
If B = 1 Then 'CheckBoxe;勾選 = 1
P = P + 1
If Not Rng(0) Is Nothing Then
Set Rng(0) = Union(Rng(0), .Range("_" & B.Name))
For i = 1 To 24 '已勾選範圍之 第1欄-第24欄
For Each E In Rng(0).Areas
Set Rng(i) = Union(E.Columns(i), Rng(i)) '同一欄位 設為同一範圍
Next
Next
Else
Set Rng(0) = .Range("_" & B.Name)
For i = 1 To 24
Set Rng(i) = Rng(0).Columns(i)
Next
End If
End If
Next
If P = 0 Then Exit Sub
Application.ScreenUpdating = False
For i = 1 To 24 '範圍有24欄
.Columns(Columns.Count - 1) = "" '清除 最後第2欄資料
.Columns(Columns.Count) = "" '清除 最後1欄資料
Rng(i).Copy Cells(1, Columns.Count) '複製欄的資料
.Columns(Columns.Count).AdvancedFilter xlFilterCopy, .Cells(1, Columns.Count - 1), Unique:=True
'進階篩選:選取不重複的資料,減少迴圈.
.Columns(Columns.Count - 1).Sort Key1:=.Cells(1, Columns.Count - 1), Order1:=xlDescending, Header:=xlNo
'排序 : 不要的資料置於底部
Set Rng(25) = .Columns(Columns.Count - 1).Cells(1) '設定要尋找的字串
With Rng(i)
Do Until Rng(25) = "___" Or Rng(25) = "0" Or Rng(25) = ""
Set Rng(0) = .Find(Rng(25), lookat:=xlWhole)
If Not Rng(0) Is Nothing Then
.Replace Rng(25), "=xxx", xlWhole '如同工作表尋找:全部取代 為錯誤的公式
.SpecialCells(xlCellTypeFormulas).Select
S = Application.CountA(Selection) / P
If S <= 1 Then
S = Application.Match(S, [AA2:AG2], -1) 'Match 的排序:大到小
Else
S = 1
End If
Selection.Value = Rng(25) '復原 取代的字串
Selection.Interior.ColorIndex = Sheet1.[AA2].Cells(1, S).Interior.ColorIndex
End If
Set Rng(25) = Rng(25).Offset(1) '尋找下一個字串
Loop
End With
Next
.Columns(Columns.Count - 1) = "" '清除 最後第2欄資料
.Columns(Columns.Count) = "" '清除 最後1欄資料
Application.ScreenUpdating = True
.CheckBoxes(Application.Caller).TopLeftCell.Select
End With
End Sub
複製代碼
作者:
cmo140497
時間:
2012-12-17 16:18
回復
9#
GBKEE
再度感謝版主幫小弟解決這個困擾已久的問題,不過小弟在試run的時候,出現了一個問題,如下圖示所示,實在不知道如何作troubleshooting,再麻煩版主一下,感恩
[attach]13577[/attach]
[attach]13578[/attach]
作者:
GBKEE
時間:
2012-12-17 16:36
本帖最後由 GBKEE 於 2012-12-17 16:45 編輯
回復
10#
cmo140497
你的資料顯示是2003版 何不在2003試看
測試12# 2010版 需是
.Columns(Columns.Count).AdvancedFilter xlFilterCopy, , .Cells(1, Columns.Count - 1), Unique:=True
複製代碼
作者:
cmo140497
時間:
2012-12-17 16:41
回復
11#
GBKEE
小弟是用office 2010 plus版,再麻煩版主幫小弟看一下,感恩
[attach]13579[/attach]
作者:
cmo140497
時間:
2012-12-17 17:01
回復
11#
GBKEE
Dear 版主:
應該是可以了,小弟得花點時間看一下,也希望版主可以不吝指導,另外小弟如果想把Total結果丟在旁邊的位址(AI5:BF28),不知是否可行?及顏色的計算好像反了,及如果均為0,不知是否可呈現代碼1的顏色,不知是否可再行修正?
還是很感謝版主您的大力的協助,感恩!
[attach]13580[/attach]
作者:
cmo140497
時間:
2012-12-17 19:22
回復
4#
Hsieh
Dear Hsieh 版主大大:
不好意思,再度打擾您了,關於小弟的問題,不知您是否有更好的作法,從GBKEE版主的作法,執行速度上會有點慢,如果方便的話,小弟將流程更簡化,直接計數不為0之Count,除以核取方塊數,計算百分比條件格式化之顏色代碼,如有您方便的話,再煩請版主您再幫忙一下,感恩!
[attach]13583[/attach]
[attach]13584[/attach]
作者:
Hsieh
時間:
2012-12-17 19:42
回復
14#
cmo140497
非常抱歉,我實在看不懂你整體流程與所需效果
請教以下問題
1、文字檔的用意是甚麼?
2、要變色的位置到底是哪個位置?
3、要變色的位置的資料是如何取得?
4、請盡可能將您的所有動作流程敘述清楚
要用檔案解釋您的問題,請用一致的檔案
作者:
cmo140497
時間:
2012-12-18 14:57
回復
15#
Hsieh
Dear Hsieh 版主 :
實在不好意思,造成您的困擾,希望您可見諒..關於您的疑問
1、文字檔的用意是甚麼?
這文字檔代表一個產品的檢查結果,小弟想知道它與其它間有沒有集中或重疊的趨勢,藉以了解並試找出可能是哪一個流程出問題
2、要變色的位置到底是哪個位置?
希望是可以在固定位置Range("AI5:BF28"),而不是每個文字檔的位置,不好意思,小弟沒有說明清楚,抱歉
3、要變色的位置的資料是如何取得?
所以小弟變更流程,三個ID相同位址只要有<>0,則計算1,三個都<>0,則計算3,將3除以核取方塊勾選的片數3=100%,則以100%之顏色
填入要變色的位置即可,毋需再用文字檔之資料與要變色之資料作比對了,不知這樣是否可行?
4、請盡可能將您的所有動作流程敘述清楚
不好意思,因為上班用公司電腦,有點Lag,上傳資料有時怪怪的,造成您的困擾,實在抱歉
希望版主再幫忙看一下,感恩,謝謝!
[attach]13594[/attach]
作者:
Hsieh
時間:
2012-12-19 01:01
回復
16#
cmo140497
不知道理解是否正確
將文字檔與程式檔至於同一資料夾試試
[attach]13602[/attach]
Sub InputData()
Dim Btn(), Mystr$, ARng As Range
fd = ThisWorkbook.Path & "\"
fs = Dir(fd & "*.txt")
With ActiveSheet
.CheckBoxes.Delete
.Cells.Clear
Do Until fs = ""
Open fd & fs For Input As #1
Do While Not EOF(1)
Line Input #1, Mystr
If InStr(Mystr, ":") > 0 Then
r = r + 1
.Cells(r, 3) = Split(Mystr, ":")(0)
If InStr(Split(Mystr, ":")(1), " ") > 0 Then
ar = Split(Split(Mystr, ":")(1), " ")
.Cells(r, 5).Resize(, UBound(ar) + 1) = ar
Else
.Cells(r, 5) = Replace(Split(Mystr, ":")(1), "ITEM", "")
ReDim Preserve Btn(s)
Btn(s) = Replace(Split(Mystr, ":")(1), "ITEM", "")
s = s + 1
End If
End If
Loop
Close #1
r = r + 1
fs = Dir
Loop
.Cells(r, 5).Resize(, UBound(ar) + 1).EntireColumn.AutoFit
For i = 0 To s - 1
With .CheckBoxes.Add(.Cells(i + 4, "A").Left, .Cells(i + 4, "A").Top, .Cells(i + 4, "A").Width, .Cells(i + 4, "A").Height)
.Characters.Text = Btn(i)
.OnAction = "Get_Rng"
End With
Next
.Range(.Range(.[E2], .[E2].End(xlDown)), .Range(.[E2], .[E2].End(xlDown)).End(xlToRight)).Copy .[AI2]
.[AI2].CurrentRegion.EntireColumn.AutoFit
Set ARng = .[AI2].CurrentRegion
ARng.Replace "___", ""
ARng.SpecialCells(xlCellTypeConstants).Value = 0
ARng.SpecialCells(xlCellTypeBlanks).Value = "___"
End With
ActiveWindow.Zoom = 75
End Sub
Sub Get_Rng()
Dim A As Range, Rng As Range, Sp As Shape, CRng As Range
With ActiveSheet
For Each Sp In .Shapes
If Sp.Name Like "Check Box*" Then
If Sp.OLEFormat.Object.Value = 1 Then
n = Sp.OLEFormat.Object.Caption
Set A = .Columns("E").Find(n, lookat:=xlWhole)
If Rng Is Nothing Then
Set Rng = A.CurrentRegion
Else
Set Rng = Union(Rng, A.CurrentRegion)
End If
End If
End If
Next
If Rng Is Nothing Then
MsgBox "Nothing"
Else
For x = 1 To Rng.Areas(1).Columns.Count
For y = 2 To Rng.Areas(1).Rows.Count
ReDim ay(1 To Rng.Areas.Count)
ReDim ary(1 To Rng.Areas.Count)
For i = 1 To Rng.Areas.Count
If Rng.Areas(i).Cells(y, x) = "000" Then .[AI2].CurrentRegion.Cells(y - 1, x).Interior.ColorIndex = 4: GoTo 10
ay(i) = Rng.Areas(i).Cells(y, x)
Next
For j = 1 To UBound(ay)
For s = 1 To UBound(ay)
If ay(j) = ay(s) Then cnt = cnt + 1
Next
ary(j) = cnt: cnt = 0
Next
g = Application.Lookup(Application.Max(ary) / Rng.Areas.Count, Array(0, 0.19, 0.39, 0.59, 0.79, 0.99, 1), Array(4, 44, 8, 6, 7, 3, 16))
With .[AI2].CurrentRegion.Cells(y - 1, x)
If .Value = "___" Then
.Interior.ColorIndex = -4142
Else
.Interior.ColorIndex = g
End If
End With
10
Next
Next
End If
End With
End Sub
複製代碼
作者:
cmo140497
時間:
2012-12-19 14:32
標題:
(已解決)如何使用VBA或函數做多個陣列數值的比較及格式化條件的設定
回復
17#
Hsieh
感謝版主不吝指教,這樣看起來真的簡單多了,對於您的大恩大德,小弟畢生難忘,太感謝您了,謝謝!
作者:
cmo140497
時間:
2012-12-19 16:17
回復
17#
Hsieh
Dear Hsieh版主 :
不好意思,再度打擾您一下,感謝版主您提供協助,小弟測試了一下,有點小小的bug,不知您是否可以再幫小弟debug一下,主要在相除母數,似乎把右列僅欲顯示的圖值,加進來了,變成任何值與0比較,均變為0,感恩
[attach]13611[/attach]
作者:
davidju041206
時間:
2012-12-19 19:49
雖無權限下載...仍謝謝您的分享...
努力增加等級中...
作者:
Hsieh
時間:
2012-12-19 23:33
回復
19#
cmo140497
Sub Get_Rng()
Dim A As Range, Rng As Range, Sp As Shape, CRng As Range
With ActiveSheet
For Each Sp In .Shapes
If Sp.Name Like "Check Box*" Then
If Sp.OLEFormat.Object.Value = 1 Then
n = Sp.OLEFormat.Object.Caption
Set A = .Columns("E").Find(n, lookat:=xlWhole)
If Rng Is Nothing Then
Set Rng = A.CurrentRegion
Else
Set Rng = Union(Rng, A.CurrentRegion)
End If
End If
End If
Next
If Rng Is Nothing Then
MsgBox "Nothing"
Else
For x = 1 To Rng.Areas(1).Columns.Count
For y = 2 To Rng.Areas(1).Rows.Count
ReDim ay(1 To Rng.Areas.Count)
ReDim ary(1 To Rng.Areas.Count)
For i = 1 To Rng.Areas.Count
ay(i) = Rng.Areas(i).Cells(y, x)
If Rng.Areas(i).Cells(y, x) = "000" Then zero = zero + 1
Next
For j = 1 To UBound(ay)
For s = 1 To UBound(ay)
If ay(j) = ay(s) Then cnt = cnt + 1
Next
ary(j) = cnt: cnt = 0
Next
g = Application.Lookup(Application.Max(ary) / Rng.Areas.Count, Array(0, 0.19, 0.39, 0.59, 0.79, 0.99, 1), Array(4, 44, 8, 6, 7, 3, 16))
With .[AI2].CurrentRegion.Cells(y - 1, x)
If .Value = "___" Then
.Interior.ColorIndex = -4142
ElseIf zero = Rng.Areas.Count Then '全部都是000
.Interior.ColorIndex = 4
Else
.Interior.ColorIndex = g
End If
zero = 0
End With
10
Next
Next
End If
End With
End Sub
複製代碼
作者:
GBKEE
時間:
2012-12-20 09:34
本帖最後由 GBKEE 於 2012-12-20 09:44 編輯
16# 檔案的程式碼,試看看程式處裡的速度是否滿意!!
Option Explicit
Const xRow As Integer = 24
Const xCol As Integer = 24
Private Sub AUTO_OPEN()
Dim Rng As Range, E As Range, xi As Integer
Sheets("Overlap").Activate
Set Rng = [A:A]
Rng.Replace "ID", "=XXX", xlWhole
Set Rng = Rng.SpecialCells(xlCellTypeFormulas, xlErrors)
ActiveSheet.CheckBoxes.Delete
For Each E In Rng.Cells
With Cells(xi + 5, "AA")
With ActiveSheet.CheckBoxes.Add(.Left, .Top, .Width, .Height)
.Caption = "Item" & xi + 1
.OnAction = "Ex_Action"
E.Offset(1, 1).Resize(xRow, xCol).Name = "_" & .Caption '設置範圍名稱
End With
End With
xi = xi + 1
Next
Rng.Value = "ID"
End Sub
Private Sub Ex_Action()
Dim cBox As Object, Rng As Range, r As Integer, y As Integer, xi As Integer
Dim Ar(), E As Variant, t As Date
t = Time
For Each cBox In ActiveSheet.CheckBoxes
If cBox.Value = 1 Then
If Rng Is Nothing Then Set Rng = Range("_" & cBox.Caption)
If Not Rng Is Nothing Then Set Rng = Union(Rng, Range("_" & cBox.Caption))
End If
Next
With Range("AI5").Resize(xRow, xCol)
.Interior.ColorIndex = xlNone
For Each cBox In .Cells
If cBox <> "___" Then cBox = 0
Next
End With
Application.ScreenUpdating = False
Range("B:Z").Interior.ColorIndex = xlNone
If Rng Is Nothing Then Exit Sub
ReDim Ar(1 To xRow, 1 To xCol) '設定:陣列大小
'******** 每一個範圍中同一位置有資料的:計數
For Each cBox In Rng.Areas '處裡每一個範圍
For r = 1 To xRow
For y = 1 To xCol
If cBox(r, y) = "___" Then GoTo 0 '不處裡
If cBox(r, y) <> 0 Then Ar(r, y) = Ar(r, y) + 1 '紀錄資料
0:
Next
Next
Next
'******** 每一個範圍中同一位置資料的計數百分比:設下顏色
For Each cBox In Rng.Areas
For r = 1 To xRow
For y = 1 To xCol
xi = 0 '百分比:歸零
If cBox(r, y) = "___" Then GoTo 1
For Each E In Array(0, 0.19, 0.39, 0.59, 0.79, 0.99, 1)
xi = xi + 1
If Ar(r, y) / Rng.Areas.Count <= E Then Exit For '取得百分比
Next
If Ar(r, y) > 0 Then cBox(r, y).Interior.ColorIndex = [AA2].Cells(1, xi).Interior.ColorIndex
'[AA2].Cells(1, xi):顏色的位置
1:
Next
Next
Next
'******** 統計範圍位置資料: 計數, 百分比顏色
With Range("AI5")
For r = 1 To xRow
For y = 1 To xCol
If .Cells(r, y) <> "___" Then
.Cells(r, y) = IIf(Ar(r, y) = "", 0, Ar(r, y))
If Ar(r, y) > 0 Then
.Cells(r, y).Interior.ColorIndex = Rng(r, y).Interior.ColorIndex
Else
.Cells(r, y).Interior.ColorIndex = [AA2].Interior.ColorIndex
End If
End If
Next
Next
End With
Application.ScreenUpdating = True
MsgBox Format(t, "開始 hh:mm:ss") & vbLf & Format(Time, "結束 hh:mm:ss") & vbLf & vbLf & Format(Time - t, "費時 hh:mm:ss")
End Sub
複製代碼
回復
19#
cmo140497
作者:
cmo140497
時間:
2012-12-21 08:08
回復
22#
GBKEE
Dear GBKEE 版主 :
實在不好意思啦,並不是有意的,真的很感謝版主及在這裡的高手們替小弟解決困擾,小弟也會從這些發問中學到不少應用,真的很感謝版主您的幫忙,感恩!
作者:
cmo140497
時間:
2012-12-21 08:24
回復
21#
Hsieh
再度感謝版主,實在感恩,謝謝!
歡迎光臨 麻辣家族討論版版 (http://forum.twbts.com/)