Option Explicit Public PlantList, PlantListWO As Variant _____________________________________________________________________________________ Function ForagPath() As String ForagPath = ReturnTopPath & "\ForagingPictures.com" If Not FileExists(ForagPath) Then MsgBox "Cannot proceed. The website folder was not found:" & vbLf & ForagPath, vbCritical, "Aborted!" End End If End Function _____________________________________________________________________________________ Private Sub BuildForagSitemap() ' is button on Dashboard sheet CreateSiteMapFromOtherSheet ForagPath End Sub _____________________________________________________________________________________ Function ScientificName(ByRef PlantList As Variant, ByVal PIvalue As String) As String ' returns html string with plant's scientific name if it exists in PlantList ' also called in Pictures processing Dim i As Integer Dim t As String ' standard name PIvalue = DropStr(PIvalue, 4) ' find row in PlantList For i = 0 To UBound(PlantList) If RemSciName(PlantList(i, 1)) = PIvalue Then If 0 < InStr(PlantList(i, 1), "[") Then t = DropStr(PlantList(i, 1), InStr(PlantList(i, 1), "[")) ScientificName = "
Scientific name: " & DropStr(t, -1) Else ScientificName = "" End If Exit Function End If Next i ScientificName = "" End Function _____________________________________________________________________________________ Function PlantLink(ByRef PlantList As Variant, ByVal PIvalue As String) As String ' returns relative link to the plant's folder Dim f As String PIvalue = DropStr(PIvalue, 4) If PIvalue = "" Then Exit Function If FileExists(ForagPath & "\plants\" & Replace(PIvalue, " ", "_")) Then ' -> we should check here. if only one, then there should not be a link PlantLink = "
More plant pictures at " & PIvalue & "" & vbCrLf End If End Function _____________________________________________________________________________________ Function GetLocation(ByVal Name As String) As String ' gets location for a foraging album name. returns a short location name from the c_TourOrder.txt file ' also called in Pictures processing ' arg: album name in string Dim i As Integer Dim a As String Dim C As Variant a = Left(Name, 12) C = GetFixedData(ForagPath & "\tours\data\c_TourOrder.txt", 13) For i = 0 To UBound(C) If C(i, 0) = a Then GetLocation = C(i, 1) Exit Function End If Next i End Function _____________________________________________________________________________________ Private Sub CombineFs() ' combines all plant names from all foraging albums ' creates: PlantData.txt and PlantDataNot.txt Dim i As Integer, j As Integer Dim f As String, t As String, resNot As String Dim D, L, res, resSort As Variant L = ListFiles(ForagPath & "\tours\data", "txt", , True, "pi_F-") ' loop for files For i = 0 To UBound(L) D = ReturnFileAsArrayOfRows(L(i)) ' pure filename f = RemoveExtension(ExtractFilename(L(i))) f = DropStr(f, 3) ' loop for rows For j = 0 To UBound(D) t = f & " 0" & Left(D(j), 3) & " " & DropStr(D(j), 4) ' is it plant or not? If Len(D(j)) > 4 Then res = AppendVectors(res, t) resSort = AppendVectors(resSort, DropStr(D(j), 4)) Else resNot = resNot & t & vbCrLf End If Next j Next i ' sort the found ones res = IndexIntoVector(res, GradeUp(resSort)) SaveIfChanged ForagPath & "\site-processing\PlantData.txt", Ravel(res, vbCrLf) SaveIfChanged ForagPath & "\site-processing\PlantDataNot.txt", resNot End Sub _____________________________________________________________________________________ Private Sub AddToPlantList() ' adds all foraging list to PlantData and returns new plants not in PlantList Dim i As Integer, j As Integer Dim S As String Dim D, L, PlantList, res As Variant ' must run before this CombineFs ' unique plants in source data D = RemDupSameOrder(ReturnColumn(GetFixedData(ForagPath & "\site-processing\PlantData.txt", 13, 5), 2)) ' our master list of plants ' -> can share L variable PlantList = GetFixedData(ForagPath & "\site-processing\PlantList.txt", 3) ' user may have added, so we sort and save PlantList = SortMatrix(PlantList, 1) For i = 0 To UBound(PlantList) S = S & TakeString(PlantList(i, 0), 3) & PlantList(i, 1) & vbCrLf Next i SaveIfChanged ForagPath & "\PlantList.txt", S ' get list of only plant names, as all that is used here L = ReturnColumn(PlantList, 1) ' we check for duplicates If UBound(L) <> UBound(RemDupSameOrder(L)) Then MsgBox "Duplicates found in PlantList.txt: " & ReturnDups(L, True), vbCritical, "Aborted" Exit Sub End If ' remove scientific names L = RemSciName(L) ' loop for data and see if member of list For i = 0 To UBound(D) If Not IsMember(L, D(i)) Then res = AppendVectors(res, D(i)) End If Next i If IsEmpty(res) Then MsgBox "No new plants found.", vbExclamation, "Done" Else L = ReadInFile(ForagPath & "\site-processing\PlantList.txt") For i = 0 To UBound(res) L = L & " " & res(i) & vbCrLf Next i SaveFile ForagPath & "\site-processing\PlantList.txt", L MsgBox UBound(res) + 1 & " new plants found and added to PlantList.txt bottom. They need to be classified and scientific name added.", vbExclamation, "Done" End If End Sub _____________________________________________________________________________________ Function RemSciName(Vec As Variant, Optional RetSciName As Boolean) As Variant ' input and output are array vectors or strings ' opt flag returns sci name instead of base (with no leading space) Dim i As Integer, j As Integer If IsArray(Vec) Then For i = 0 To UBound(Vec) j = InStr(Vec(i), "[") If j <> 0 Then If RetSciName Then Vec(i) = DropStr(Vec(i), j - 1) Else Vec(i) = Left(Vec(i), j - 2) End If End If Next i RemSciName = Vec Else j = InStr(Vec, "[") If j <> 0 Then If RetSciName Then RemSciName = DropStr(Vec, j - 1) Else RemSciName = Left(Vec, j - 2) End If Else If RetSciName Then RemSciName = "" Else RemSciName = Vec End If End If End If End Function _____________________________________________________________________________________ Private Sub ProcessAllPlants() ' is button on Dashboard sheet ' builds menu section for ForagingPictures.com home page, and all plant indexes and htms ' also sorts PlantList.txt Dim i As Integer, j As Integer, k As Integer, q As Integer Dim f As String, FP As String, H As String, t As String, tBN As String, tWO As String, ToursPath As String Dim PIs, PIsTot, PIsU, PlantData, PlantDataNames, PlantIndex, PlantListBN, PlantListMO, PlantListMOi As Variant Dim Data, SortList, SubList, temp, TourOrder, UniqLocs As Variant FP = ForagPath ToursPath = FP & "\tours" PlantIndex = GetFixedData(FP & "\site-processing\PlantIndex.txt", 3) ' our master list of the different plants SortPlantList 1 PlantList = GetFixedData(FP & "\site-processing\PlantList.txt", 3) ' we check that there are no blanks left from additions For i = 0 To UBound(PlantList) If PlantList(i, 0) = "" Then MsgBox "PlantList has blank in first column. Needs one of the six group codes.", vbCritical, "Aborted" Exit Sub End If Next i ' convenient to have the plant names in two vectors temp = ReturnColumn(PlantList, 1) PlantListWO = RemSciName(temp) PlantListBN = RemSciName(temp, True) ' we collect names in menu order, for slide show to follow ReDim PlantListMO(UBound(PlantListWO)) ReDim PlantListMOi(UBound(PlantListWO)) ' all picture entries, columns: 0-pi_ filename, 1-picture number, 2-plant name in plant index PlantData = GetFixedData(FP & "\site-processing\PlantData.txt", 13, 5) PlantDataNames = ReturnColumn(PlantData, 2) ' check for any plants not in PlantList For i = 0 To UBound(PlantData) If Not IsMember(PlantListWO, PlantData(i, 2)) Then MsgBox "Plant: " & PlantData(i, 2) & " in PlantData was not found in PlantList.", vbCritical, "Aborted" Exit Sub End If Next i ' check that plant in PlantList has some members in the data For i = 0 To UBound(PlantListWO) If Not IsMember(PlantDataNames, PlantListWO(i)) Then MsgBox "Plant '" & PlantListWO(i) & "' found in PlantList has no members in the PlantData. You need to rerun Add to PlantList.", vbCritical, "Aborted" Exit Sub End If Next i ' get tour location list and save locations only in alpha order. cols: 0-tour folder name, 1-location TourOrder = SortMatrix(GetFixedData(ToursPath & "\data\c_TourOrder.txt", 13), 1) ' ~~~~~~ home page index files ~~~~~~ ' table of contents H = "" & vbCrLf & vbCrLf & "
" & vbCrLf & vbCrLf ' process for each category k = 0 For i = 0 To UBound(PlantIndex) SubList = ReturnColumn(SelectRows(PlantList, RowsKeyMatches(ReturnColumn(PlantList, 0), PlantIndex(i, 0))), 1) H = H & "

" & PlantIndex(i, 1) & " (" & 1 + UBound(SubList) & " plants)

" H = H & "" & vbCrLf & vbCrLf Next i If IsEmpty(PlantListMO(UBound(PlantListMO))) Then SortPlantList 0 MsgBox "Some plant in PlantList has a group that was not found in PlantIndex's six groups." & vbLf & "The PlantList has been sorted on the first column. Look for non-valid code.", vbCritical, "Aborted" Exit Sub End If ' save and insert count numbers into pages f = FP & "\index.htm" InsertIntoHtm f, H t = Format(1 + UBound(PlantData), "#,###") & " pictures of " & (UBound(PlantList) + 1) & " different plants and mushrooms. Pictures were taken on " & UBound(TourOrder) + 1 InsertIntoHtm f, t, "" InsertIntoHtm f, Year(Date), "" ' insert top list of tours - in season sort ' we start with ascending date order for secondary sort SubList = SortMatrix(TourOrder, 0) ReDim SortList(UBound(SubList)) For i = 0 To UBound(SubList) SortList(i) = Mid(SubList(i, 0), 8, 5) Next i SubList = SelectRows(SubList, GradeUp(SortList)) H = "" ReDim temp(UBound(SubList)) For i = 0 To UBound(SubList) t = SubList(i, 0) & "/"">" & SubList(i, 1) & " - " & ReturnFormattedDate(SubList(i, 0)) & "" temp(i) = t H = H & "
  • " & vbCrLf & "Site Map", "") H = Replace(H, "DOCTYPE html>" & vbCrLf, "DOCTYPE html>" & vbCrLf & vbCrLf & "" & vbCrLf & vbCrLf) f = FP & "\plants\index.htm" SaveIfChanged f, H ' ~~~~~~ create annotated walks ~~~~~~ ' in season order (sublist is TourOrder already in that order) ' we have the title to start, we beef it up to a full entry f = FP & "\tours\data" For i = 0 To UBound(SubList) j = 1 + UBound(ReturnFileAsArrayOfRows(f & "\pd_" & SubList(i, 0) & ".txt")) temp(i) = "
    (" & j & " pictures)
    " & vbCrLf Data = ReturnFileAsArrayOfRows(f & "\ai_" & SubList(i, 0) & ".txt") t = RemoveHTML(Data(1)) j = InStr(t, " ") If 0 < j Then t = DropStr(t, j + 5) End If temp(i) = temp(i) & t & "

    " & vbCrLf & vbCrLf Next i ' in season order InsertIntoHtm FP & "\tours\index.htm", Ravel(temp) & vbCrLf ' we append the locations as the first column of a matrix to make alpha sorting easier Data = Catenate1dot5(ReturnColumn(SubList, 1), temp) ' in alpha order InsertIntoHtm FP & "\tours\index-alpha.htm", Ravel(ReturnColumn(SortMatrix(Data, 0), 1)) & vbCrLf ' we append the filenames as the first column of a matrix to make date sorting easier temp = Catenate1dot5(ReturnColumn(SubList, 0), temp) ' in descending date order InsertIntoHtm FP & "\tours\index-desc-date.htm", Ravel(ReturnColumn(SortMatrix(temp, 0, , True), 1)) & vbCrLf ' in ascending date order InsertIntoHtm FP & "\tours\index-asc-date.htm", Ravel(ReturnColumn(SortMatrix(temp, 0), 1)) & vbCrLf ' ~~~~~~ build location table ~~~~~~ ' find unique locations UniqLocs = RemDupSameOrder(ReturnColumn(TourOrder, 1)) ' we get all tour plant lists upfront for efficiency ReDim PIs(UBound(TourOrder)) For i = 0 To UBound(TourOrder) PIs(i) = ReturnColumn(GetFixedData(ToursPath & "\data\pi_" & TourOrder(i, 0) & ".txt", 4), 1) ' also all in list for counting PIsTot = AppendVectors(PIsTot, PIs(i)) Next i ' and in a nest of plant lists by unique locations ReDim PIsU(UBound(UniqLocs)) For i = 0 To UBound(PIsU) For j = 0 To UBound(TourOrder) If TourOrder(j, 1) = UniqLocs(i) Then PIsU(i) = AppendVectors(PIsU(i), PIs(j)) End If Next j Next i ' build table heading H = "PlantTotal
    Picture
    Count" For i = 0 To UBound(UniqLocs) H = H & "" & Replace(UniqLocs(i), " ", "
    ") & "" Next i H = H & "" & vbCrLf ' loop for plants t = "" For i = 0 To UBound(PlantListMO) ' we test if index category has changed, and we put in a section heading If t <> PlantListMOi(i) Then H = H & "" & PlantListMOi(i) & "" & vbCrLf End If t = PlantListMOi(i) ' the plant name in the first column H = H & "
    " & PlantListMO(i) & "" ' total picture count for plant in second column H = H & "" & CountInVector(PIsTot, PlantListMO(i)) & "" ' loop for unique locations For j = 0 To UBound(UniqLocs) H = H & "" ' get count for this location q = CountInVector(PIsU(j), PlantListMO(i)) If q <> 0 Then H = H & q End If H = H & "" Next j H = H & "" & vbCrLf Next i InsertIntoHtm FP & "\plant-locations.htm", H & vbCrLf ' ~~~~~~ build table of counts of unique plants in each walk ~~~~~~ ReDim PIsTot(UBound(TourOrder), 5) ' loop for tours (is already in alpha sort) temp = ReturnColumn(PlantIndex, 0) For i = 0 To UBound(TourOrder) SubList = RemoveEmptiesInVector(RemDupSameOrder(PIs(i))) ' convert to the 6 types For j = 0 To UBound(SubList) k = Iota2(temp, PlantList(Iota2(PlantListWO, SubList(j)), 0)) PIsTot(i, k) = PIsTot(i, k) + 1 Next j Next i ' create code string H = "" t = "" For i = 0 To UBound(TourOrder) ' we test if index category has changed, and we put in a section heading If t <> TourOrder(i, 1) Then H = H & "" & TourOrder(i, 1) & "" & vbCrLf End If t = TourOrder(i, 1) H = H & "" & ReturnFormattedDate(TourOrder(i, 0)) & "" k = 0 For j = 0 To 5 H = H & "" & PIsTot(i, j) & "" k = k + PIsTot(i, j) Next j H = H & "" & k & "" H = H & "" & vbCrLf Next i InsertIntoHtm FP & "\plant-counts.htm", H & vbCrLf ' ~~~~~~ index/htm files for plant list - processing taking place on Pics sheet ~~~~~~ ' put in menu order PlantList = SelectRows(PlantList, Iota2V(PlantListWO, PlantListMO)) PlantListWO = PlantListMO ' loop for plants/directories For i = 0 To UBound(PlantList) ' force directory existence On Error Resume Next MkDir FP & "\plants\" & Replace(PlantListWO(i), " ", "_") On Error GoTo 0 ' list of pictures included for this plant temp = RowsKeyMatches(PlantData, PlantListWO(i), 2) ' build list of folder/numbers for this plant ReDim SortList(UBound(temp)) ReDim SubList(UBound(temp)) For j = 0 To UBound(temp) SortList(j) = Mid(PlantData(temp(j), 0), 8, 5) SubList(j) = PlantData(temp(j), 0) & "/" & PlantData(temp(j), 1) Next j ' save our virtual list SaveFile ToursPath & "\data\list_temp.txt", Ravel(SubList, vbCrLf) ' create logical order in season order t = Ravel(GradeUp(SortList), " ", 1) t = DropStr(t, -1) & vbCrLf SaveFile ToursPath & "\data\i_temp.txt", t ' create folder files Pflg = True BuildAlbumSub FP & "\plants\", PlantListWO(i), True, True, False Next i Kill ToursPath & "\data\list_temp.txt" Kill ToursPath & "\data\i_temp.txt" ' ~~~ update copyright year in tours folder InsertIntoHtm ToursPath & "\index.htm", Year(Date), "" InsertIntoHtm ToursPath & "\index-alpha.htm", Year(Date), "" InsertIntoHtm ToursPath & "\index-asc-date.htm", Year(Date), "" InsertIntoHtm ToursPath & "\index-desc-date.htm", Year(Date), "" ' we have navigation ' -> note that the navigation at the top of the home page is dummy navigation. it is not in the nav order ProcessAllNavRowsSub "ForagingPictures" ' copy from main index to the other three index pages f = ToursPath & "\index.htm" TransferNavCode f, ToursPath & "\index-alpha.htm" TransferNavCode f, ToursPath & "\index-asc-date.htm" TransferNavCode f, ToursPath & "\index-desc-date.htm" End Sub _____________________________________________________________________________________ Private Sub RenamePlant() ' is button on Dashboard sheet ' renames plant, cleans up directories of source names, and adds redirect record ' name input, on sheet. names can include botanical name. will be stripped from old. used for new Dim i As Integer, j As Integer Dim f As String, NewName As String, NewPath As String, OldName As String, OldPath As String, t As String Dim D, PlantData, PlantList, PlantListWO, PDrows, PLrow As Variant ' we restore the yellow background color of the input fields, as pasting from the web clears it RestoreInputCells "OldPlantName" RestoreInputCells "NewPlantName" ' get names from sheet OldName = Range("OldPlantName").Value If OldName = "" Then Range("OldPlantName").Select MsgBox "Must input old name.", vbCritical, "Aborted" Exit Sub Else OldName = RemSciName(OldName) End If NewName = Range("NewPlantName").Value If NewName = "" Then Range("NewPlantName").Select MsgBox "Must input new name.", vbCritical, "Aborted" Exit Sub End If If OldName = RemSciName(NewName) Then Range("OldPlantName").Select If 0 < InStr(NewName, "[") Then t = vbLf & "To add botanical name edit the ListPlant.txt file." End If MsgBox "Old and New names can't be the same." & t, vbCritical, "Aborted" Exit Sub End If ' all picture entries, columns: 0-pi_ filename, 1-picture number, 2-plant name in plant index PlantData = GetFixedData(ForagPath & "\site-processing\PlantData.txt", 13, 5) ' find which data files have the old name PDrows = RowsKeyMatches(PlantData, OldName, 2) If IsEmpty(PDrows) Then MsgBox "Old name not found in PlantData.txt.", vbCritical, "Aborted" Exit Sub End If ' our master list of the different plants PlantList = GetFixedData(ForagPath & "\site-processing\PlantList.txt", 3) PlantListWO = RemSciName(ReturnColumn(PlantList, 1)) ' find old name in list PLrow = Iota2(PlantListWO, OldName) If IsEmpty(PLrow) Then MsgBox "Old name not found in PlantList.txt. Note that the name is case sensitive. Best to copy from the list to the input field.", vbCritical, "Aborted" Exit Sub End If ' rename in List, sort, and save PlantList(PLrow, 1) = NewName ' -> they could be doing a merge, which would create a duplicate ' -> need test NewName = RemSciName(NewName) PlantList = SortMatrix(PlantList, 1) For i = 0 To UBound(PlantList) t = t & Left(PlantList(i, 0) & " ", 3) & PlantList(i, 1) & vbCrLf Next i SaveFile ForagPath & "\PlantList.txt", t ' ~~ rename in all source files, e.g. pi_'s ' this is inefficient, as it saves for each instance in the file. but real simple code For i = 0 To UBound(PDrows) f = ForagPath & "\tours\data\pi_" & PlantData(PDrows(i), 0) & ".txt" D = ReturnFileAsArrayOfRows(f) j = CInt(PlantData(PDrows(i), 1)) - 1 D(j) = Left(D(j), 4) & NewName SaveFile f, Ravel(D, vbCrLf) Next i ' rebuild PlantData CombineFs OldName = Replace(OldName, " ", "_") NewName = Replace(NewName, " ", "_") ' rename folder OldPath = ForagPath & "\plants\" & OldName NewPath = ForagPath & "\plants\" & NewName ' it could be a merge If FileExists(NewPath) Then Kill OldPath Else Name OldPath As NewPath End If ' add permanent redirect record f = ForagPath & "\.htaccess" SaveFile f, ReadInFile(f) & "Redirect 301 /plants/" & OldName & " /plants/" & NewName & vbCrLf End Sub _____________________________________________________________________________________ Private Sub ProcessWalkTours() ' is button on Dashboard sheet ' runs all foraging albums listed there, e.g. starting with F- ' also the virtual album ForagingOther Range("PicIndFlag").Value = True Range("PicHtmFlag").Value = True Range("PicFilter").Value = "F-" BuildAllAlbums Range("PicFilter").Value = "" BuildAlbumSub PicPath("ForagingOther"), "ForagingOther", True, True End Sub _____________________________________________________________________________________ Private Sub PostPlantListCover() SortPlantList 1 End Sub _____________________________________________________________________________________ Private Sub SortPlantList(SortCol As Integer) Dim i As Integer Dim t As String Dim PlantList As Variant ' our master list of the different plants PlantList = GetFixedData(ForagPath & "\site-processing\PlantList.txt", 3) ' sort, and save if it has changed (as new additions are put on the bottom) PlantList = SortMatrix(PlantList, SortCol) For i = 0 To UBound(PlantList) t = t & Left(PlantList(i, 0) & " ", 3) & PlantList(i, 1) & vbCrLf Next i SaveIfChanged ForagPath & "\site-processing\PlantList.txt", t End Sub _____________________________________________________________________________________ Private Function ReturnFormattedDate(ByVal DateIn As String) As String ' read in date in format F-YYYY-MM-DD ' returns: Month d, yyyy Dim Months As Variant Months = Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December") ReturnFormattedDate = Months(Mid(DateIn, 8, 2) - 1) & " " & RemLead0s(Right(DateIn, 2)) & ", " & Mid(DateIn, 3, 4) End Function _____________________________________________________________________________________ Private Sub SplitForagingVBACode() ' is button on dashboard VBAtext2Text ForagPath & "\site-processing\VBA-code.txt" End Sub _____________________________________________________________________________________