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 & "
" & 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
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
_____________________________________________________________________________________