寫在前面
我很多年前看過晨間日志的奇跡這一本書,我深受啟發(fā),這本書的中心思想就是通過九宮格的方式寫連體日志,自己可以方便查找而有而且有激情去完成這個日志,書中推薦的方法是使用excel寫日志。但是自己總感覺用excel過于麻煩,打開電腦,寫日志,可能10幾分鐘過去了。自己曾嘗試使用其他方法,如印象筆記,有道云筆記,onenote,但是都沒有堅持下來,主要原因還是寫日志的過程過于復(fù)雜,沒有辦法宏觀的看自己取得了哪些成果和進步,而且時間往往都比較緊張,沒有辦法在早晨完成日志。導(dǎo)致最后變成了月計劃周計劃。自己也一直想打造一款個人的日志軟件,想使用django+vue,但是一直沒有想好數(shù)據(jù)如何存儲,如果存在數(shù)據(jù)庫,搭建在云服務(wù)器上,可能還需要花費額外的金錢,而且便宜的云數(shù)據(jù)庫往往速度不是很快。直到最近遇到了vba這個語言,突然深受啟發(fā),開始使用vba打造一款excel的日志軟件。
使用excel打造個人日志系統(tǒng)的整體邏輯
整體上使用excel打造個人日志系統(tǒng),就類似于通過一個表單提交數(shù)據(jù)到數(shù)據(jù)庫當中,在這里一個sheet頁里存的是一個表單,另外一個sheet頁存儲excel提交的信息,相當于數(shù)據(jù)庫。
在Excel當中可以添加VB宏,相當于后端邏輯??梢酝ㄟ^插入一些形狀作,為一些前端的控件,然后把控件和宏進行關(guān)聯(lián),點擊控件執(zhí)行宏的邏輯。
接下來將一步一步教你如何打造這款日志系統(tǒng)。
寫日記頁面介紹
在寫日記頁面主要有兩個表單,第一個表單是默認是當天的日期,然后可以在九宮格中填入當天需要記下的日志,點擊提交按鈕,將會將數(shù)據(jù)存儲到excel中的晨間日記數(shù)據(jù)庫中。第二個表單主要目的是可以查看過去編寫的日志,感受到自己的變化,默認信息是去年同一天記錄的日志。在這個表單中也可以切換日期,通過切換年、切換日、或者點擊今天切換日期,也可以在日期單元格指定具體的日期,點擊查詢,將會切換到具體的日期。點擊重新編輯將會將第二個表單的中的信息覆蓋到第一個表單中,允許你重新編輯該天信息。編輯后點擊提交按鈕,將會把指定日期的信息重新覆蓋。
使用宏開發(fā)組件
在WPS中選擇開發(fā)工具,然后選擇VB宏就可以添加個人的宏代碼,點擊對應(yīng)的sheet頁,在該頁面添加需要實現(xiàn)的宏。
第一個重要的宏就是實現(xiàn)將寫日記頁面中的數(shù)據(jù)提交到晨間日記數(shù)據(jù)庫頁面中存儲的功能,如下兩圖
提交宏
宏代碼如下
Sub 提交_Click()
Dim x As Integer, y As Long, z As Integer
y = Sheets("晨間日記數(shù)據(jù)庫").[a65536].End(xlUp).Row + 1
brr = Sheets("晨間日記數(shù)據(jù)庫").Range("a2:a" & y)
t = Sheets("寫日記").Range("l16")
arr = Array(Sheets("寫日記").Range("l16"), Sheets("寫日記").Range("L18"), Sheets("寫日記").Range("L19"), Sheets("寫日記").Range("L20"), Sheets("寫日記").Range("L21"), Sheets("寫日記").Range("L22"), Sheets("寫日記").Range("L23"), Sheets("寫日記").Range("B5"), Sheets("寫日記").Range("i5"), Sheets("寫日記").Range("p5"), Sheets("寫日記").Range("B15"), Sheets("寫日記").Range("p15"), Sheets("寫日記").Range("B25"), Sheets("寫日記").Range("i25"), Sheets("寫日記").Range("p25"))
If IsEmpty(brr) Then
Sheets("晨間日記數(shù)據(jù)庫").Range("a" & y).Resize(1, UBound(arr) + 1) = arr
Else
For x = 1 To UBound(brr)
If t = brr(x, 1) Then
i = MsgBox("相同日期的數(shù)據(jù)已錄入,是否覆蓋?", 4, "警告")
If i = vbNo Then Exit Sub
Sheets("晨間日記數(shù)據(jù)庫").Range("a" & x + 1).Resize(1, UBound(arr) + 1) = arr
GoTo line1:
End If
Next
Sheets("晨間日記數(shù)據(jù)庫").Range("a" & y).Resize(1, UBound(arr) + 1) = arr
End If
line1:
MsgBox "提交成功"
Range("AH16") = Range("l16")
Range("B5:V13,B15:H23,P15:V23,B25:H33,I25:O33,P25:V33,l18:O23").ClearContents
ActiveWorkbook.Save
End Sub
代碼的具體含義如下:
- 定義變量:x,y,z,和數(shù)組變量brr和arr。
- 計算晨間日記數(shù)據(jù)庫頁面目前已有的數(shù)據(jù)行數(shù),然后將新數(shù)據(jù)添加到下一行(即初始化變量y)。
- 將晨間日記數(shù)據(jù)庫頁面中所有的日期數(shù)據(jù)(即a2到a[y])存儲在數(shù)組變量brr中,并將寫日記頁面中的所有需要提交的數(shù)據(jù)存儲在數(shù)組變量arr中。
- 如果數(shù)組brr為空,則說明數(shù)據(jù)表中還沒有任何數(shù)據(jù),直接將arr數(shù)組存儲到a[y]到a[y]+UBound(arr)+1行中。
- 如果數(shù)組brr非空,則表示數(shù)據(jù)表中已經(jīng)有數(shù)據(jù),需要對它們逐一進行比對,判斷新添加的數(shù)據(jù)是否重復(fù)。如果存在相同記錄則提醒用戶進行覆蓋或直接退出,然后將新的數(shù)據(jù)覆蓋原來的數(shù)據(jù)。
- 提交數(shù)據(jù)成功后,清空寫日記頁面中的數(shù)據(jù),并將日期數(shù)據(jù)存儲在AH16單元格中。最后,提示用戶提交成功,并保存當前工作表。
至此已經(jīng)完成了一個重要的功能,存儲日志數(shù)據(jù)到晨間日記數(shù)據(jù)庫中,最后晨間日記數(shù)據(jù)庫效果如下:
以上的功能已經(jīng)滿足了基本需求。但是有的時候可能想去修改某一天的日志,如果這時候去數(shù)據(jù)庫中修改,可能不是很方便,沒有九宮格看的直觀好看,這時候如果開發(fā)一個控件,把數(shù)據(jù)同步過來,并修改,那這樣會方便直觀很多。
另外,晨間日志的奇跡主要是把今天跟去年的同一天進行對比,這樣可以看到自己的進步,從而也可以讓自己更有動力去寫日志。
整體實現(xiàn)邏輯如下圖,首次打開寫日記sheet頁,在第二個九宮格里展示的是去年的同一天。可以通過年和日的左右控件去切換年和切換日,也可以點擊今天或者切換到指定的日期,對應(yīng)日期的信息會同步到9宮格當中,點擊重新編輯會同步信息到第一個九宮格,允許自己重新編輯并存儲到晨間日記數(shù)據(jù)庫中。
日期切換宏
如下是日期切換涉及到的宏
首先是日期切換組件的代碼,宏的代碼如下
Sub 上一年_Click()
Dim DQdate As Date, NDate As Date, ts As Integer
If Sheets("晨間日記數(shù)據(jù)庫").Range("A2").Value <> "" Then
NDate = Sheets("晨間日記數(shù)據(jù)庫").Range("A2")
End If
If IsDate(Range("AH16").Value) Then
DQdate = Range("AH16")
Else
MsgBox "請確保輸入的日期有效。"
Exit Sub
End If
ts = 1
If DQdate > NDate Then
Range("AH16") = DateSerial(Year(DQdate) - ts, Month(DQdate), Day(DQdate))
If Range("AH16") >= NDate Then
result = GetDiaryData()
Else
MsgBox "那一天還沒有開始寫日志,跳轉(zhuǎn)到默認的時間"
result = GoToDefault()
End If
Else
MsgBox "已經(jīng)達到最小年份,無需跳轉(zhuǎn)"
End If
Sub 下一年_Click()
Dim DQdate As Date, ts As Integer
t = Date
If Range("AH16").Value <> "" Then DQdate = Range("AH16")
If Year(Range("AH16")) < Year(t) And Range("AH16") <> "" Then
Range("AH16") = DateSerial(Year(DQdate) + 1, Month(DQdate), Day(DQdate))
result = GetDiaryData()
Else
MsgBox "未來可期,但要活在當下"
End If
End Sub
Sub 今天_Click()
result = GoToToday()
End Sub
Sub 上一日_Click()
Dim DQdate As Date, NDate As Date, ts As Integer
If Sheets("晨間日記數(shù)據(jù)庫").Range("A2").Value <> "" Then NDate = Sheets("晨間日記數(shù)據(jù)庫").Range("A2")
If Range("AH16").Value <> "" Then DQdate = Range("AH16")
ts = 1
If Range("AH16") <> "" And Range("AH16") > NDate Then
Range("AH16") = DateSerial(Year(DQdate), Month(DQdate), Day(DQdate) - ts)
result = GetDiaryData()
Else
MsgBox "也許正是這一天,您決定寫日志來改變自己,但沒來得及記錄,無論怎樣,好好享受當下吧"
result = GoToDefault()
End If
End Sub
Sub 下一日_Click()
Dim DQdate As Date, ts As Integer
t = Date
If Range("AH16").Value <> "" Then DQdate = Range("AH16")
If Range("AH16") < t And Range("AH16") <> "" Then
Range("AH16") = DateSerial(Year(DQdate), Month(DQdate), Day(DQdate) + 1)
result = GetDiaryData()
Else
MsgBox "未來可期,但要活在當下"
End If
End Sub
Function GoToDefault() As Variant
Range("AH16") = DateSerial(Year(Date) - 1, Month(Date), Day(Date))
result = GetDiaryData()
End Function
Function GoToToday() As Variant
Range("AH16") = DateSerial(Year(Date), Month(Date), Day(Date))
result = GetDiaryData()
End Function
下面是代碼的詳細解釋:
-
Sub 上一年_Click():這個子程序用于在工作表中顯示上一年的晨間日記記錄。首先獲取當前工作表中的日期值和晨間日記數(shù)據(jù)庫最早日期的日期值。如果最早日期的日期值不為空,則將其賦值給變量 NDate。如果當前選定日期不為空,則將其賦值給變量 DQdate。
另外還對最早日期的日期有效性進行判斷,確保是日期的格式。代碼分別在年份和日期上限制用戶,年份不能小于日志系統(tǒng)的最小年份,日期不能小于日期系統(tǒng)的最小日期
-
Sub 下一年_Click():這個子程序用于在工作表中顯示下一年的晨間日記記錄。首先獲取當前工作表中的日期值和當前的系統(tǒng)日期值。如果當前選定日期不為空,則將其賦值給變量 DQdate。如果當前選定日期的年份小于系統(tǒng)日期的年份,則計算下一年的日期并將其賦值給當前選定日期。接著調(diào)用 GetDiaryData() 函數(shù)來獲取該日期的日志記錄,并將返回值賦值給變量 result。
如果當前選定日期的年份大于或等于系統(tǒng)日期的年份,則彈出消息框提示“未來可期,但要活在當下”。
-
Sub 今天_Click():這個子程序用于在工作表中顯示今天的晨間日記記錄。首先調(diào)用 GoToToday() 函數(shù)將當前選定日期設(shè)置為今天日期,并獲取該日期的日志記錄,并將返回值賦值給變量 result,用于提交后快速重新修改。
-
Sub 上一日_Click():這個子程序用于在工作表中顯示前一天的晨間日記記錄。首先獲取當前工作表中的日期值和最早日志記錄的日期值。如果最早日志記錄日期值不為空,則將其賦值給變量 NDate。如果當前選定日期不為空,則將其賦值給變量 DQdate。
如果當前選定日期大于最新日志記錄的日期,則計算前一天的日期并將其賦值給當前選定日期。接著調(diào)用 GetDiaryData() 函數(shù)來獲取該日期的日志記錄,并將返回值賦值給變量 result。
如果當前選定日期小于或等于最早日志記錄的日期,則彈出消息框提示“也許正是這一天,您決定寫日志來改變自己,但沒來得及記錄,無論怎樣,好好享受當下吧”,并將日期切換到系統(tǒng)的默認時間。
-
Sub 下一日_Click():這個子程序用于在工作表中顯示后一天的晨間日記記錄。首先獲取當前工作表中的日期值和當前的系統(tǒng)日期值。如果當前選定日期不為空,則將其賦值給變量 DQdate。如果當前選定日期小于系統(tǒng)日期,則計算后一天的日期并將其賦值給當前選定日期。接著調(diào)用 GetDiaryData() 函數(shù)來獲取該日期的日志記錄,并將返回值賦值給變量 result。
如果當前選定日期大于或等于系統(tǒng)日期,則彈出消息框提示“未來可期,但要活在當下”。
-
Function GoToDefault():這個函數(shù)用于將當前選定日期設(shè)置為去年的今天日期,并獲取該日期的日志記錄。首先計算去年的今天日期并將其賦值給當前選定日期。接著調(diào)用 GetDiaryData() 函數(shù)來獲取該日期的日志記錄,并將返回值賦值給變量 result。
-
Function GoToToday():跳轉(zhuǎn)到今天。
-
代碼中涉及到的GetDiaryData函數(shù),將在下面解釋。
查詢宏
宏代碼如下
Sub 查詢_Click()
result = GetDiaryData()
End Sub
查詢宏實現(xiàn)功能是輸入日期后點擊查詢就可以查詢對應(yīng)日期的數(shù)據(jù),主要調(diào)用了GetDiaryData()函數(shù),如下
Function GetDiaryData() As Variant
Dim diarySheet As Worksheet, logSheet As Worksheet
Dim diaryRange As Range
Dim logDate As Date, diaryDate As Date, ah17Date As Variant
Dim dateValue As Date
Dim i As Integer, j As Integer
Set diarySheet = Worksheets("晨間日記數(shù)據(jù)庫")
Set logSheet = Worksheets("寫日記")
Set diaryRange = diarySheet.Range("A2", diarySheet.Cells(diarySheet.Rows.Count, "A").End(xlUp)).Resize(, 17)
y = diarySheet.[a65536].End(xlUp).Row + 1
brr = diarySheet.Range("a2:a" & y)
If IsEmpty(brr) Then
MsgBox "晨間日記數(shù)據(jù)庫目前為空"
Else
foundDate = False
If Not IsDate(logSheet.Range("AH17").Value) Then
MsgBox "輸入的日期不正確,請重新輸入,九宮格將恢復(fù)到默認的數(shù)據(jù)"
result = GoToDefault()
Exit Function
End If
diaryDate = logSheet.Range("AH16").Value
For i = 1 To diaryRange.Rows.Count
logDate = diaryRange.Cells(i, 1).Value
If DateDiff("d", logDate, diaryDate) = 0 Then
logSheet.Range("AH18") = diaryRange.Cells(i, 2).Value
logSheet.Range("AH19") = diaryRange.Cells(i, 3).Value
logSheet.Range("AH20") = diaryRange.Cells(i, 4).Value
logSheet.Range("AH21") = diaryRange.Cells(i, 5).Value
logSheet.Range("AH22") = diaryRange.Cells(i, 6).Value
logSheet.Range("AH23") = diaryRange.Cells(i, 7).Value
logSheet.Range("X5") = diaryRange.Cells(i, 8).Value
logSheet.Range("AE5") = diaryRange.Cells(i, 9).Value
logSheet.Range("AL5") = diaryRange.Cells(i, 10).Value
logSheet.Range("X15") = diaryRange.Cells(i, 11).Value
logSheet.Range("AL15") = diaryRange.Cells(i, 12).Value
logSheet.Range("X25") = diaryRange.Cells(i, 13).Value
logSheet.Range("AE25") = diaryRange.Cells(i, 14).Value
logSheet.Range("AL25") = diaryRange.Cells(i, 15).Value
foundDate = True
Exit For '找到了就退出循環(huán),沒有必要繼續(xù)循環(huán)
End If
Next i
If Not foundDate Then '循環(huán)結(jié)束后仍沒有找到
result = ClearValue()
End If
End If
End Function
Function ClearValue() As Variant
Dim logSheet As Worksheet
Set logSheet = Worksheets("寫日記")
logSheet.Range("AH18").Value = ""
logSheet.Range("AH19").Value = ""
logSheet.Range("AH20").Value = ""
logSheet.Range("AH21").Value = ""
logSheet.Range("AH22").Value = ""
logSheet.Range("AH23").Value = ""
logSheet.Range("X5").Value = ""
logSheet.Range("AE5").Value = ""
logSheet.Range("AL5").Value = ""
logSheet.Range("X15").Value = ""
logSheet.Range("AL15").Value = ""
logSheet.Range("X25").Value = ""
logSheet.Range("AE25").Value = ""
logSheet.Range("AL25").Value = ""
End Function
具體邏輯如下:
- 獲取工作表對象和數(shù)據(jù)范圍對象
首先獲取兩個工作表對象:‘晨間日記數(shù)據(jù)庫’和’寫日記’,并且獲取’晨間日記數(shù)據(jù)庫’工作表中日記數(shù)據(jù)的范圍,用diaryRange表示。
- 判斷晨間日記數(shù)據(jù)庫是否為空,為空直接拋出晨間日記數(shù)據(jù)庫目前為空,否則繼續(xù)向下執(zhí)行
- 遍歷日記數(shù)據(jù)范圍
利用For循環(huán)遍歷diaryRange中每一行的日記數(shù)據(jù),獲取日記日期logDate,并與輸入的日記日期diaryDate進行比較。如果兩個日期相等,就將對應(yīng)的日記數(shù)據(jù)復(fù)制到’寫日記’工作表的指定單元格中,并設(shè)置foundDate為True表示找到了對應(yīng)日期的日記。
- 輸入日期不正確
如果輸入的日期不正確,彈出提示框提示用戶重新輸入,并返回到默認的數(shù)據(jù)狀態(tài),即調(diào)用GoToDefault()函數(shù)。
- 沒有找到對應(yīng)日期的日記
如果循環(huán)結(jié)束后仍然沒有找到對應(yīng)日期的日記,清空單元格信息,可以切換其他日期繼續(xù)查看
編輯宏
這個宏主要是把右邊九宮格的內(nèi)容同步到左邊九宮格,這樣可以對指定日期的記錄重新編輯,并提交到晨間日志數(shù)據(jù)庫中。代碼邏輯如下
Sub 編輯_Click()
If Range("B5").Value <> "" And Range("i5").Value <> "" And Range("p5").Value <> "" Then
i = MsgBox("本日內(nèi)容將在左側(cè)九宮格中編輯," & Chr(10) & "但是左側(cè)九宮格中已有內(nèi)容," & Chr(10) & "是否覆蓋?", 4, "警告")
If i = vbNo Then Exit Sub
Range("l16") = Range("AH16")
Range("L18") = Range("AH18")
Range("L19") = Range("AH19")
Range("L20") = Range("AH20")
Range("L21") = Range("AH21")
Range("L22") = Range("AH22")
Range("L23") = Range("AH23")
Range("B5") = Range("X5")
Range("i5") = Range("AE5")
Range("p5") = Range("AL5")
Range("B15") = Range("X15")
Range("p15") = Range("AL15")
Range("B25") = Range("X25")
Range("i25") = Range("AE25")
Range("p25") = Range("AL25")
Else
Range("l16") = Range("AH16")
Range("L18") = Range("AH18")
Range("L19") = Range("AH19")
Range("L20") = Range("AH20")
Range("L21") = Range("AH21")
Range("L22") = Range("AH22")
Range("L23") = Range("AH23")
Range("B5") = Range("X5")
Range("i5") = Range("AE5")
Range("p5") = Range("AL5")
Range("B15") = Range("X15")
Range("p15") = Range("AL15")
Range("B25") = Range("X25")
Range("i25") = Range("AE25")
Range("p25") = Range("AL25")
End If
End Sub
在這個宏中,如果B5、i5和p5單元格中都有值,那么就會出現(xiàn)一個警告詢問是否覆蓋左側(cè)九宮格中的內(nèi)容。如果用戶點擊否,宏就會終止;如果用戶點擊是,宏就會執(zhí)行復(fù)制右邊九宮格的內(nèi)容到左邊。
如果B5、i5和p5單元格中有任何一個是空白的,那么宏就會直接執(zhí)行以上操作,而不彈出警告提示。
Workbook中的宏
work中的宏可以設(shè)置打開workbook時的默認值,代碼如下,設(shè)置AH16
單元格的值為去年今天,l16
單元格的值為今天,最后調(diào)用前面提到的GetDiaryData()
函數(shù),獲取去年今天的值。
Private Sub Workbook_Open()
Sheet1.Range("AH16") = DateSerial(Year(Date) - 1, Month(Date), Day(Date))
Sheet1.Range("l16") = Date
result = Worksheets("寫日記").Evaluate("GetDiaryData()")
End Sub
插入圖形并關(guān)聯(lián)宏
如上我打造的個人日志系統(tǒng)里的所有組件都是通過,插入菜單,插入形狀插入的,插入后可以右擊選擇指定宏,即可進行關(guān)聯(lián)對應(yīng)的宏。
最后對插入的形狀進行保護,編輯形狀的大小和屬性,便完成了該系統(tǒng)的打造。
資源連接
鏈接:https://pan.baidu.com/s/1IFzvo-9lcjR17TUHiGo3Sw?pwd=wyli
提取碼:wyli文章來源:http://www.zghlxwxcb.cn/news/detail-418761.html
寫在后面
這是我第一次使用VB語言編寫較多組件,其中可能有一些語法有些冗余,另外有一些異常場景可能沒有考慮到,但是經(jīng)過測試,基本滿足了日常需求。
開發(fā)日志系統(tǒng)的目的主要是對自己的日志情況有一個宏觀的把控,并且通過Excel進行縱向?qū)Ρ?,很容易方便快捷的對比自己有哪些進步,取得了哪些成就。
對于自己目標的實現(xiàn)也可以在日志系統(tǒng)插入一些自己想要達成的目標,比如說如果想打卡一個習慣,可以通過excel標注顏色確定事項的優(yōu)先級,通過添加列標注目標完成的狀態(tài)。
Excel在于開源,自己可以寫一大堆函數(shù)實現(xiàn)個人需求,數(shù)據(jù)存儲也相對安全,個人感覺平時使用Excel寫日記其實并不是特別方便。個人習慣喜歡使用一些同步比較快的軟件,寫日志的時間盡量縮短在三分鐘之內(nèi)??梢允褂糜械涝乒P記等軟件自定義模板功能,這樣自己可以在周末時間把之前寫過的日志進行整理省時省力。文章來源地址http://www.zghlxwxcb.cn/news/detail-418761.html
到了這里,關(guān)于使用Excel打造一款個人日志系統(tǒng)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!