Option Explicit _____________________________________________________________________________________ Private Sub ProcessOneNavRow() ' is button on AddNav sheet AddFolderNavCode GetNavCodeRow End Sub _____________________________________________________________________________________ Private Sub ProcessAllNavRows() ' is button on AddNav sheet ProcessAllNavRowsSub Range("NavFilter").Value End Sub _____________________________________________________________________________________ Sub ProcessAllNavRowsSub(Filter As String) Dim Okay As Boolean Dim i As Integer For i = 1 To Range("NavInputMatrix").Rows.Count If Range("NavInputMatrix").Cells(i, 2).Value <> "" Then Okay = True If Len(Filter) > 0 Then If 0 = InStr(Range("NavInputMatrix").Cells(i, 2).Value, Filter) Then Okay = False End If If Okay Then Application.StatusBar = "Processing " & i & " " & ExtractFilename(Range("NavInputMatrix").Cells(i, 2).Value) & "..." AddFolderNavCode i End If End If Next i Application.StatusBar = False End Sub _____________________________________________________________________________________ Private Sub CreateSiteMapFromNavCode() ' is button on AddNav sheet CreateSiteMapFromOtherSheet Range("NavInputMatrix").Cells(GetNavCodeRow, 2).Value End Sub _____________________________________________________________________________________ Sub AddFolderNavCode(ByVal i As Integer) ' sub to ProcessOneNavRow, ProcessAllNavRows and AddNavCodeFromOtherSheet ' N.B. this requires the index file have a .htm extension. for html include filename on sheet Dim DownLevelFlag As Boolean, HtmOnlyFlag As Boolean, StripFlag As Boolean Dim b As Integer, Char2Drop As Integer, e As Integer, j As Integer Dim D As String, H As String, TestStr As String Dim NextFN As String, NextFT As String, Path As String, Prefix As String, PrevFN As String, PrevFT As String Dim FileNames, FilePaths, FileTitles, res, res0, res1 As Variant Path = Range("NavInputMatrix").Cells(i, 2).Value H = Dec2Bin(Range("NavInputMatrix").Cells(i, 1).Value, 4) ' some get htms built If Mid(H, 1, 1) = "1" Then CreateFolderFiles Path, H Exit Sub End If ' other options (2-DownLevelFlag, 4-HtmOnlyFlag, 8-StripFlag) DownLevelFlag = Mid(H, 2, 1) = "1" HtmOnlyFlag = Mid(H, 3, 1) = "1" StripFlag = Mid(H, 4, 1) = "1" ' get filenames and filepaths from index file If Right(Path, 3) = "htm" Then res = GetFilesFromPage(Path, HtmOnlyFlag) Else res = GetFilesFromPage(Path & "\index.htm", HtmOnlyFlag) End If FileNames = res(0) FilePaths = res(1) ' when navigation is looping through a lower level ' --> this is no longer in use, but code left here If DownLevelFlag Then For i = 0 To UBound(FilePaths) res = GetFilesFromPage(FilePaths(i), HtmOnlyFlag) res0 = AppendVectors(res0, res(0)) res1 = AppendVectors(res1, res(1)) Next i FileNames = res0 FilePaths = res1 End If ' ~~ titles used for navigation labels ReDim FileTitles(UBound(FileNames)) ' does our top navigation have its own labels? If 0 < InStr(Path, "topnav") Then res = ReturnFileAsArrayOfRows(Path) For i = 0 To UBound(res) D = res(i) D = DropStr(D, InStr(D, ">")) D = Left(D, InStr(D, "<") - 1) If D <> "" Then FileTitles(i) = D End If Next i End If ' get nav titles from the files For i = 0 To UBound(FilePaths) If IsEmpty(FileTitles(i)) Then FileTitles(i) = ExtractPageTitle(FilePaths(i)) End If Next i ' remove repetitious prefixes: either option set on sheet, or default of stripping to a common colon location ' --> if strip isn't working, put a Stop here and look at the FileTitles variable If StripFlag Then Char2Drop = CountOfRepChars(FileTitles) Else b = InStr(FileTitles(0), ": ") If b <> 0 Then b = b + 1 Char2Drop = WorksheetFunction.min(CountOfRepChars(FileTitles), b) End If ' ~~ loop to modify files For i = 0 To UBound(FileNames) If i = 0 Then PrevFN = FileNames(UBound(FileNames)) PrevFT = FileTitles(UBound(FileTitles)) Else PrevFN = FileNames(i - 1) PrevFT = FileTitles(i - 1) End If If i = UBound(FileNames) Then NextFN = FileNames(0) NextFT = FileTitles(0) Else NextFN = FileNames(i + 1) NextFT = FileTitles(i + 1) End If H = "
" & vbCrLf ' sometimes they are folders, instead of files, so we give up-folder prefix If 0 < InStr(FileNames(i), "/") Then Prefix = Left("../../../../", 3 * CountInString(FileNames(i), "/")) Else Prefix = "" End If H = H & "
← " & DropStr(PrevFT, Char2Drop) & "
" & vbCrLf H = H & "
" & DropStr(NextFT, Char2Drop) & " →
" & vbCrLf H = H & "
" & vbCrLf D = ReadInFile(FilePaths(i)) ' find existing nav code to remove b = InStr(D, "
") e = 7 + res(2) Else MsgBox "You need to stick some dummy navcode in the file " & ExtractFilename(FilePaths(i)) & " for this macro to find.", vbCritical, "Aborted" Exit Sub End If SaveIfChanged FilePaths(i), Left(D, b) & H & DropStr(D, b + e), D Next i End Sub _____________________________________________________________________________________ Sub CreateFolderFiles(Path As String, H As String, Optional Names As Variant, Optional ByVal SubIndexName As String) ' requires files FolderData.txt and FolderInfo.txt to be present in Path. sort order comes from index.htm ' for sub-folders, it processes them like the AddFolderNavCode macro above ' both get the pages and order from the master file Dim DownLevelFlag As Boolean, StripFlag As Boolean, SubFlag As Boolean Dim Char2Drop As Integer, i As Integer, j As Integer Dim D As String, f As String, FileSuffix As String, IndexFileName As String, SaveFileName As String, SaveNavCode As String Dim NextFN As String, NextFT As String, PrevFN As String, PrevFT As String Dim BackLinksVec, CustomCSS, CustomDesc, Data, FilePaths, Info, NavTitles, res0, res1, SSs, temp, TopLinks As Variant ' needs row in matrix, so we pass instead of row StripFlag = Mid(H, 4, 1) = "1" ' when we are navigating at a lower level ' --> when downlevel is used the parent htms must also be created for stats to use DownLevelFlag = Mid(H, 2, 1) = "1" ' when we getting the navigation not from the index file, we need a suffix If Right(Path, 3) = "htm" Then IndexFileName = DropStr(ExtractFilename(Path), -4) FileSuffix = "-" & IndexFileName Path = ExtractPath(Path) Else IndexFileName = "index" End If ' get files from index page, to get navigation order If IsMissing(Names) Then Names = GetFilesFromPage(Path & "\" & IndexFileName & ".htm", False) Else SubFlag = True End If FilePaths = Names(1) Names = RemoveExtensions(Names(0)) ' ~~ for downlevel processing we loop to get data. -> can only be htm files, no subfolders If DownLevelFlag Then ReDim DataCounts(UBound(Names)) For i = 0 To UBound(Names) ' we combine names and paths temp = GetFilesFromPage(FilePaths(i), True) res0 = AppendVectors(res0, temp(0)) res1 = AppendVectors(res1, temp(1)) ' we combine data temp = ExtractData(Path & "\FolderData-" & Names(i) & ".txt", "", 5) Data = MatrixConcat1stDim(Data, temp) ' we keep the last as our Info file Info = ReturnFileAsArrayOfRows(Path & "\FolderInfo-" & Names(i) & ".txt") ' we make a combined backlinks file (will be same length as data) BackLinksVec = AppendVectors(BackLinksVec, RepeatArray(Info(1), UBound(temp) + 1)) ' we may have custom CSS code f = Path & "\FolderCSS" & FileSuffix & ".txt" If FileExists(f) Then CustomCSS = MatrixConcat1stDim(CustomCSS, ExtractData(f, "*")) End If Next i Names = RemoveExtensions(res0) FilePaths = res1 Else ' get data file, columns: 0-filename, 1-head title, 2-page title, 3-page code Data = ExtractData(Path & "\FolderData" & FileSuffix & ".txt", "", 5) ' get folder info: 0-name of css files (";" delims if > 1), 1-backlinks string, 2-description (opt), ' 3-sub-indexes, 4-shortcut icon string Info = ReturnFileAsArrayOfRows(Path & "\FolderInfo" & FileSuffix & ".txt") ' we may have custom CSS code f = Path & "\FolderCSS" & FileSuffix & ".txt" If FileExists(f) Then CustomCSS = ExtractData(f, "*") End If ' we may have custom Descriptions --> not implemented when DownLevel f = Path & "\FolderDesc" & FileSuffix & ".txt" If FileExists(f) Then CustomDesc = ExtractData(f, "*") End If ' we may have custom Top Links --> not implemented when DownLevel f = Path & "\FolderTopLinks" & FileSuffix & ".txt" If FileExists(f) Then TopLinks = ExtractData(f, "*") End If End If ' some are options and not in files, so we need to pad ReDim Preserve Info(4) ' if there are sub-indexes, then they get their own calls to this macro If Not SubFlag Then If 0 < Len(Info(3)) Then If 0 < InStr(Info(3), ";") Then SSs = Split(Info(3), ";") Else SSs = Array(Info(3)) End If For i = 0 To UBound(SSs) temp = GetFilesFromPage(Path & "\" & SSs(i) & ".htm", False) ' the StripFlag option is turned off, as a sub-index can have all the same head names CreateFolderFiles Path, "00000", temp, SSs(i) Next i End If End If ' we may have multiple stylesheets If 0 < InStr(Info(0), ";") Then SSs = Split(Info(0), ";") Else SSs = Array(Info(0)) End If ' ~~ we have to add to Data the heading titles from the sub-folders j = UBound(Data) ' pad data for the new rows Data = AddRowsToMatrix(Data, CountInString(Ravel(Names), "/")) ' loop to find sub-folders For i = 0 To UBound(Names) If Right(Names(i), 1) = "/" Then j = j + 1 Data(j, 0) = Names(i) Data(j, 1) = ExtractPageTitle(FilePaths(i), True) End If Next i ' remove from data names we aren't using and sort temp = Iota2V(ReturnColumn(Data, 0), Names) If IsMember(temp, "") Then MsgBox Names(Iota2(temp, "")) & " not found in" & vbLf & DropStr(Path, 1 + Len(Range("TopPath").Value)) & "\FolderData" & FileSuffix & ".txt file", vbCritical, "Aborted." Exit Sub End If Data = SelectRows(Data, temp) If Not DownLevelFlag Then BackLinksVec = RepeatArray(Info(1), UBound(Data) + 1) End If ' remove repetitious prefixes NavTitles = ReturnColumn(Data, 1) For i = 0 To UBound(NavTitles) NavTitles(i) = RemFromStrFront(NavTitles(i)) Next i ' --> if strip isn't working, put a Stop here and look at the FileTitles variable in Locals window If StripFlag Then Char2Drop = CountOfRepChars(NavTitles) Else j = InStr(NavTitles(0), ": ") If j <> 0 Then j = j + 1 Char2Drop = WorksheetFunction.min(CountOfRepChars(NavTitles), j) End If ' loop for files For i = 0 To UBound(Data) ' ~~ common navigation block If i = 0 Then PrevFN = Data(UBound(Data), 0) PrevFT = NavTitles(UBound(NavTitles)) Else PrevFN = Data(i - 1, 0) PrevFT = NavTitles(i - 1) End If If i = UBound(Data) Then NextFN = Data(0, 0) NextFT = NavTitles(0) Else NextFN = Data(i + 1, 0) NextFT = NavTitles(i + 1) End If ' we don't use the file extension, so we have to add If Right(PrevFN, 1) <> "/" Then PrevFN = PrevFN & ".htm" If Right(NextFN, 1) <> "/" Then NextFN = NextFN & ".htm" ' prefix f = Left("../../../../", 3 * CountInString(Data(i, 0), "/")) H = "
" & vbCrLf H = H & "
← " & DropStr(PrevFT, Char2Drop) & "
" & vbCrLf H = H & "
" & DropStr(NextFT, Char2Drop) & " →
" & vbCrLf H = H & "
" & vbCrLf If Right(Data(i, 0), 1) = "/" Then ' ~~~~ add navigation to index file in sub-folder ~~~~ f = Path & "\" & DropStr(Data(i, 0), -1) & "\index.htm" D = ReadInFile(f) ' find existing nav code to remove. -> you must put in dummy nav code to initialize j = InStr(D, "
") SaveIfChanged f, Left(D, j) & H & DropStr(D, j + 7 + temp(2)), D Else ' ~~~~ or create htm page ~~~~ SaveNavCode = H H = "" & vbCrLf H = H & "" ' we may have a shortcut icon If Not IsEmpty(Info(4)) Then H = H & "" End If H = H & vbCrLf & "" & vbCrLf H = H & "" & Data(i, 1) & "" & vbCrLf ' we may have a description If Not IsEmpty(CustomDesc) Then temp = Iota2(ReturnColumn(CustomDesc, 0), Data(i, 0)) If Not IsEmpty(temp) Then H = H & "" & vbCrLf End If ElseIf 0 < Len(Info(2)) Then H = H & "" & vbCrLf End If H = H & "" & vbCrLf H = H & "" & vbCrLf ' loop for stylesheets For j = 0 To UBound(SSs) H = H & "" & vbCrLf Next j ' we may have custom CSS code for the file If Not IsEmpty(CustomCSS) Then temp = Iota2(ReturnColumn(CustomCSS, 0), Data(i, 0)) If Not IsEmpty(temp) Then temp = Split(DropStr(CustomCSS(temp, 1), -2), vbCrLf) H = H & "" & vbCrLf End If End If ' when the title is on two or three lines, we need another style sheet. which must be in same folder j = CountInString(Data(i, 2), "
") If j = 1 Then H = H & "" & vbCrLf ElseIf j = 2 Then H = H & "" & vbCrLf End If H = H & "" & vbCrLf H = H & "
" & vbCrLf & vbCrLf ' we may have top links If Not IsEmpty(TopLinks) Then temp = Iota2(ReturnColumn(TopLinks, 0), Data(i, 0)) If Not IsEmpty(temp) Then H = H & "
" & DropStr(TopLinks(temp, 1), -2) & "
" & vbCrLf & vbCrLf End If End If H = H & "
" & BackLinksVec(i) If SubFlag Then H = H & " Sub Index →" End If H = H & "
" & vbCrLf & vbCrLf H = H & SaveNavCode & vbCrLf H = H & "
" & Data(i, 2) & "
" & vbCrLf & vbCrLf H = H & "
" & vbCrLf & "
" & vbCrLf & vbCrLf ' below the sticky header H = H & Data(i, 3) & vbCrLf & "" & vbCrLf & "" SaveIfChanged Path & "\" & Data(i, 0) & ".htm", H & vbCrLf End If Next i End Sub _____________________________________________________________________________________ Private Sub EditFolderInfo() EditFolderSub "Info" End Sub _____________________________________________________________________________________ Private Sub EditFolderData() EditFolderSub "Data" End Sub _____________________________________________________________________________________ Private Sub EditFolderCSS() EditFolderSub "CSS" End Sub _____________________________________________________________________________________ Private Sub EditFolderDesc() EditFolderSub "Desc" End Sub _____________________________________________________________________________________ Private Sub EditFolderSub(Suffix As String) Dim f As String, Path As String Path = Range("NavInputMatrix").Cells(GetNavCodeRow, 2).Value If Right(Path, 3) = "htm" Or Right(Path, 4) = "html" Then Path = ExtractPath(Path) End If f = Path & "\Folder" & Suffix & ".txt" If FileExists(f) Then CallNotepad f Else MsgBox "The " & ExtractFilename(DropStr(Path, -1)) & " folder does not have a " & Suffix & " file.", vbCritical, "Aborted" End If End Sub _____________________________________________________________________________________ Function GetPageAfterNav(ByVal Path As String) As String ' removes heading, plus nav code, if there is any ' used by navigation and sitemap ' if more than one navbar, then takes after the last Dim b As Integer, e As Integer Dim D As String Dim res As Variant If Dir(Path) = "" Then D = ExtractFilename(Path) Path = DropStr(ExtractPath(Path), -1) MsgBox "You have a link to a file that does not exist: " & D & vbLf & "In this folder: " & Path & vbLf & "Search for the filename to find where called.", vbCritical, "Aborted!" End End If D = ReadInFile(Path) res = AllInStr(D, "
")) Else b = res(UBound(res)) - 1 res = AllInStr(DropStr(D, b), "
") e = 7 + res(2) D = DropStr(D, b + e) End If GetPageAfterNav = D End Function _____________________________________________________________________________________ Function FindAllLinkLocations(ByVal D As String, ByVal Filter As String) As Variant Dim i As Integer, j As Integer Dim Locs As New Collection Dim b, e, H As Variant H = AllInStr(D, " href=""") ' remove any before or after we want them b = AllInStr(D, "") e = AllInStr(D, "") If Not IsEmpty(b) Or Not IsEmpty(e) Then If IsEmpty(b) Then b = Array(0) If IsEmpty(e) Then e = Array(Len(D)) If e(0) < b(0) Then b = AppendVectors(Array(0), b) End If If e(UBound(e)) < b(UBound(b)) Then e = AppendVectors(e, Array(Len(D))) End If Set Locs = Nothing For i = 0 To UBound(H) If ((b(0) < H(i)) And (H(i) < e(UBound(e)))) Then Locs.Add H(i) End If Next i H = Collection2Array(Locs) If 0 < UBound(b) Then Set Locs = Nothing For i = 0 To UBound(b) - 1 For j = 0 To UBound(H) If ((b(i + 1) < H(j)) Or (H(j) < e(i))) Then Locs.Add H(j) End If Next j Next i H = Collection2Array(Locs) End If End If FindAllLinkLocations = H End Function _____________________________________________________________________________________ Function IncludeLinks(ByVal D As String, ByVal strts As Variant, IncludeList As Variant) As Variant ' D is web page in string If IsEmpty(strts) Then Exit Function Dim i As Integer, j As Integer Dim Locs As New Collection For i = 0 To UBound(strts) For j = 0 To UBound(IncludeList) If Mid(D, strts(i), Len(IncludeList(j))) = IncludeList(j) Then Locs.Add strts(i) End If Next j Next i IncludeLinks = Collection2Array(Locs) End Function _____________________________________________________________________________________ Function ExcludeLinks(ByVal D As String, ByVal strts As Variant, ExcludeList As Variant) As Variant ' D is web page in string ' returns empty array when strts is empty If IsEmpty(strts) Then Exit Function Dim Test As Boolean Dim i As Integer, j As Integer Dim Locs As New Collection For i = 0 To UBound(strts) Test = True For j = 0 To UBound(ExcludeList) If Mid(D, strts(i), Len(ExcludeList(j))) = ExcludeList(j) Then Test = False End If Next j If Test Then Locs.Add strts(i) Next i ExcludeLinks = Collection2Array(Locs) End Function _____________________________________________________________________________________ Function GetFilesFromPage(ByVal SourceFilePath As String, ByVal HtmOnly As Boolean) As Variant ' sub function to AddFolderNavCode and CreateFolderFiles ' optionally gets only the htm file links (Top pictures menu uses for nav between categories) Dim Tbool As Boolean Dim i As Integer, j As Integer Dim D As String, Ext As String, S As String Dim FileNames, FilePaths, H, t As Variant D = GetPageAfterNav(SourceFilePath) If Len(D) = 0 Then Exit Function H = FindAllLinkLocations(D, "Intrapage Navigation") H = ExcludeLinks(D, H, Array(" href=""http", " href="".", " href=""#", " href=""sitemap")) ' ~~ loop for each name on page ' -> prob needs test for empty For i = 0 To UBound(H) If H(i) <> 0 Then ' extract name S = DropStr(D, H(i) + 6) S = Left(S, InStr(S, """") - 1) ' keep only htm files and folders Tbool = (Right(S, 1) = "/" And Not HtmOnly) Or Right(S, 3) = "htm" Or Right(S, 4) = "html" ' we want to filter out when calling an htm file in a subfolder, and links more than one level deep Tbool = Tbool And 0 = InStr(DropStr(S, -1), "/") If Tbool Then ' we need to check if not a dup If Not IsMember(FileNames, S) Then FileNames = AppendVectors(FileNames, Array(S)) If "/" = Right(S, 1) Then S = S & "index.htm" End If If Right(SourceFilePath, 3) = "htm" Or Right(SourceFilePath, 4) = "html" Then FilePaths = AppendVectors(FilePaths, Array(ExtractPath(SourceFilePath) & S)) Else FilePaths = AppendVectors(FilePaths, Array(SourceFilePath & "\" & S)) End If End If End If End If Next i GetFilesFromPage = Array(FileNames, FilePaths) End Function _____________________________________________________________________________________ Function GetNavCodeRow(Optional PathFlag As Boolean) As Variant Dim Row As Integer Dim Name As String Row = Range("NavNum").Value ' we check quality of row number and album name existence If Row < 1 Or Row > Range("NavInputMatrix").Rows.Count Then Sheets("AddNav").Select Range("NavNum").Select MsgBox "Must enter row number within range of input matrix: 1 to " & Range("NavInputMatrix").Rows.Count & ".", vbCritical, "Aborted!" End ElseIf 0 < InStr(Range("NavNum").Value, ".") Then Sheets("AddNav").Select Range("NavNum").Select MsgBox "Row Number must be Integer.", vbCritical, "Aborted!" End End If If PathFlag Then Name = Range("NavInputMatrix").Cells(Row, 2).Value If Len(Name) = 0 Then Sheets("AddNav").Select Range("NavInputMatrix").Cells(Row, 2).Select MsgBox "Album Name for selected row is empty.", vbCritical, "Aborted!" End End If GetNavCodeRow = Name Else GetNavCodeRow = Row End If End Function _____________________________________________________________________________________ Private Sub ViewNavPage() ' is button on AddNav sheet Dim Path As String Path = GetNavCodeRow(True) If Right(Path, 4) <> ".htm" Then Path = Path & "\index.htm" End If ActiveWorkbook.FollowHyperlink Path End Sub _____________________________________________________________________________________ Private Sub SortInputRangeNav() ' is button on AddNav sheet Range("NavInputMatrix").Sort Key1:=Range("C6") Sheets("AddNav").Select End Sub _____________________________________________________________________________________ Sub AddNavCodeFromOtherSheet(ByVal Path As String) ' must have this workbook active ThisWorkbook.Activate Dim i As Integer Dim t As String, UPath As String UPath = UCase(Path) ' loop through paths on AddNav sheet to find which one For i = 1 To Range("NavInputMatrix").Rows.Count t = UCase(Range("NavInputMatrix").Cells(i, 2).Value) If t <> "" Then ' this would fail on sub-strings, but we are okay, as long as data in in alpha order If Left(t, Len(UPath)) = UPath Then GoTo FoundIt End If Next i MsgBox "Path Not Found on AddNav sheet:" & vbLf & Path, vbCritical, "Aborted!" Exit Sub FoundIt: MRFlag = True Range("NavNum").Value = i MRFlag = False AddFolderNavCode i End Sub _____________________________________________________________________________________ Private Sub OpenNavFolder() ' button on AddNav sheet Dim Path As String Path = Range("NavInputMatrix").Cells(GetNavCodeRow, 2).Value If Right(Path, 3) = "htm" Then Path = ExtractPath(Path) End If CallExplorer Path End Sub _____________________________________________________________________________________