1、實現原理:
艾賓浩斯seid一個知識點學習后要復習8次后可達到永久記憶(這個還有待驗證。。。),其復習間隔時間分別為1d、2d、4d、7d、15d、30d、90d、180d。
2、實現效果:
在一個sheet【學習清單】里按日期記錄每天的學習內容(如圖1),在另外一個sheet【當日復習清單】里提供日期選擇功能,並根據選擇日期切換顯示當日需要復習的內容(如圖2)。
圖1:

圖2:

3、用到的知識點:
3.1 二分查找算法:
隨着記錄的學習內容漸漸多,需要節省查找時間。使用這個算法的前提是每天的學習內容是按日期升序排序的。
3.2 vba返回單元格的3種方式:
sheet1.range("b2:d4");sheet1.cells(3,4);sheet1.[a2:d6]。因為涉及不同sheet表之間的取值,所以需要標明sheet頁名稱。
3.3 返回一列單元格有數據的最后一行:
Worksheets("學習清單").Range("a1048576").End(3).Row
Range("a1048576").End(3) 代表從 a1048576單元格往前查找到的第一個有數據的單元格。
Range("a1048576").End(3).Row 表示A列單元格最下面一個有數據的單元格的行號。
End(3)這個3代表常量 xlup,表示向上搜索。
2003版本后一張Excel工作表,最多可以包括1048576行和16384列。
3.4 vba中實現數值改變單元格后觸發事件:
假設要判斷的值在A1,則代碼為:
Dim oldval
Private Sub Worksheet_Activate()
oldval = [a1]
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
If oldval <> [a1] Then
oldval = [a1]
'在此輸入操作代碼
End If
End Sub
4、全部vba代碼如下:
1 Dim date_select '選擇的復習日期 2 Dim array_a(8) '存儲復習間隔,共8個間隔 3 4 Private Sub Worksheet_Activate() 5 date_select = Worksheets("當日復習清單").[b1] 6 array_a(8) = 1 7 array_a(7) = 2 8 array_a(6) = 4 9 array_a(5) = 7 10 array_a(4) = 15 11 array_a(3) = 30 12 array_a(2) = 90 13 array_a(1) = 180 14 End Sub 15 Private Sub Worksheet_Change(ByVal Target As Range) 16 If date_select <> Worksheets("當日復習清單").[b1] Then 17 date_select = Worksheets("當日復習清單").[b1] 18 Worksheets("當日復習清單").[a4:d1048576] = "" 19 20 Dim array_b(8) '存儲所選擇的復習日期對應的學習日期,共8個 21 Dim hang_all, hang_half '學習日期的有數據的最后行號和中間行號 22 Dim find_begin, find_end '查找學習日期時的開始行號和結束行號 23 24 Dim hang_now '存儲復習內容的長度,每次選擇日期后會更新為0 25 hang_now = 0 26 27 hang_all = Worksheets("學習清單").Range("a1048576").End(3).Row '返回一列單元格有數據的最后一行 28 hang_half = Int(hang_all / 2) 29 30 For i = 1 To 8 '計算學習日期 31 array_b(i) = date_select - array_a(i) 32 33 If Worksheets("學習清單").Cells(hang_half, 1) <= array_b(i) Then '利用二分查找算法提高查找效率 34 Do While Worksheets("學習清單").Cells(hang_half, 1) = Worksheets("學習清單").Cells(hang_half - 1, 1) 35 hang_half = hang_half - 1 36 Loop '解決:中間行號的學習日期和前后日期相等的情況 37 find_begin = hang_half 38 find_end = hang_all 39 Else 40 Do While Worksheets("學習清單").Cells(hang_half, 1) = Worksheets("學習清單").Cells(hang_half + 1, 1) 41 hang_half = hang_half + 1 42 Loop '解決:中間行號的學習日期和前后日期相等的情況 43 find_begin = 2 44 find_end = hang_half 45 End If 46 47 For j = find_begin To find_end '根據學習日期返回復習內容 48 If Worksheets("學習清單").Cells(j, 1) = array_b(i) Then 49 hang_now = hang_now + 1 50 Worksheets("當日復習清單").Cells(hang_now + 3, 1) = hang_now 51 Worksheets("當日復習清單").Cells(hang_now + 3, 2) = Worksheets("學習清單").Cells(j, 2) '復習內容 52 Worksheets("當日復習清單").Cells(hang_now + 3, 3) = Worksheets("學習清單").Cells(j, 3) '時長 53 Worksheets("當日復習清單").Cells(hang_now + 3, 4) = Worksheets("學習清單").Cells(j, 1) '學習日期 54 End If 55 Next j 56 find_find = j '因為要找的學習日期是升序存儲的,所以查找下一個學習日期時可以把查找的開始行號改為j 57 Next i 58 Dim time_sum 59 time_sum = Application.WorksheetFunction.Sum(Worksheets("當日復習清單").Range("c:c")) 60 Worksheets("當日復習清單").[a2] = "共需復習" & hang_now & "個內容,共需" & time_sum & "分鍾" 61 End If 62 End Sub
