No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

305 líneas
11KB

  1. <%
  2. '=======================================================================================================================
  3. ' IMPORT FILE HELPERS
  4. ' Reads CSV / XLSX / XLS uploads into a header array + rows dictionary, and normalizes values for the businesses table.
  5. '
  6. ' ImportFile_Read(path, maxRows) returns a Scripting.Dictionary:
  7. ' "headers" -> Array of column names
  8. ' "rows" -> Scripting.Dictionary (0-based index -> Array of string values), at most maxRows rows (0 = all)
  9. '=======================================================================================================================
  10. Function ImportFile_UploadDir()
  11. Dim fso : Set fso = CreateObject("Scripting.FileSystemObject")
  12. Dim dir : dir = fso.GetAbsolutePathName(Server.MapPath("/") & "\..\uploads")
  13. If Not fso.FolderExists(dir) Then fso.CreateFolder dir
  14. ImportFile_UploadDir = dir
  15. End Function
  16. ' Returns the full path of the stored upload for a token, or "" when the token is malformed or the file is missing.
  17. Function ImportFile_PathForToken(token)
  18. Dim re : Set re = New RegExp
  19. re.Pattern = "^[0-9A-Fa-f]{32}$"
  20. ImportFile_PathForToken = ""
  21. If Not re.Test(token) Then Exit Function
  22. Dim fso, ext, p
  23. Set fso = CreateObject("Scripting.FileSystemObject")
  24. For Each ext In Array("csv", "xlsx", "xls")
  25. p = ImportFile_UploadDir() & "\" & token & "." & ext
  26. If fso.FileExists(p) Then
  27. ImportFile_PathForToken = p
  28. Exit Function
  29. End If
  30. Next
  31. End Function
  32. Function ImportFile_NewToken()
  33. Dim tl : Set tl = CreateObject("Scriptlet.TypeLib")
  34. ImportFile_NewToken = Replace(Replace(Replace(Left(CStr(tl.Guid), 38), "{", ""), "}", ""), "-", "")
  35. Set tl = Nothing
  36. End Function
  37. Function ImportFile_Read(path, maxRows)
  38. Dim ext : ext = LCase(Mid(path, InStrRev(path, ".") + 1))
  39. If ext = "csv" Then
  40. Set ImportFile_Read = ImportFile_ReadCsv(path, maxRows)
  41. Else
  42. Set ImportFile_Read = ImportFile_ReadExcel(path, ext, maxRows)
  43. End If
  44. End Function
  45. '---------------------------------------------------------------------------------------------------------------------
  46. ' CSV
  47. '---------------------------------------------------------------------------------------------------------------------
  48. Function ImportFile_ReadCsv(path, maxRows)
  49. Dim stm, text
  50. Set stm = Server.CreateObject("ADODB.Stream")
  51. stm.Type = 2
  52. stm.Charset = "utf-8"
  53. stm.Open
  54. stm.LoadFromFile path
  55. text = stm.ReadText
  56. stm.Close
  57. ' Not valid UTF-8 (replacement character present): re-read as Windows-1252, which is what Excel "CSV" exports use.
  58. If InStr(text, ChrW(65533)) > 0 Then
  59. stm.Charset = "windows-1252"
  60. stm.Open
  61. stm.LoadFromFile path
  62. text = stm.ReadText
  63. stm.Close
  64. End If
  65. Set stm = Nothing
  66. text = Replace(text, vbCrLf, vbLf)
  67. text = Replace(text, vbCr, vbLf)
  68. ' Pick the delimiter that appears most in the first line.
  69. Dim firstLine, delim, best, cand, c
  70. firstLine = Left(text, InStr(text & vbLf, vbLf) - 1)
  71. delim = ","
  72. best = 0
  73. For Each cand In Array(",", ";", vbTab, "|")
  74. c = Len(firstLine) - Len(Replace(firstLine, cand, ""))
  75. If c > best Then best = c : delim = cand
  76. Next
  77. Dim lines, i, line, pending, all, rec
  78. lines = Split(text, vbLf)
  79. Set all = CreateObject("Scripting.Dictionary")
  80. pending = ""
  81. For i = 0 To UBound(lines)
  82. line = lines(i)
  83. If Len(pending) > 0 Then
  84. line = pending & vbLf & line
  85. pending = ""
  86. End If
  87. ' An odd number of quotes means a quoted field continues onto the next physical line.
  88. If ((Len(line) - Len(Replace(line, """", ""))) Mod 2) = 1 And i < UBound(lines) Then
  89. pending = line
  90. ElseIf Len(Trim(line)) > 0 Then
  91. all.Add all.Count, ImportFile_SplitCsvLine(line, delim)
  92. If maxRows > 0 And all.Count > maxRows Then Exit For
  93. End If
  94. Next
  95. Set ImportFile_ReadCsv = ImportFile_Pack(all)
  96. End Function
  97. Function ImportFile_SplitCsvLine(line, delim)
  98. If InStr(line, """") = 0 Then
  99. ImportFile_SplitCsvLine = Split(line, delim)
  100. Exit Function
  101. End If
  102. Dim fields(), n, i, ch, cur, inQ
  103. ReDim fields(Len(line))
  104. n = 0 : cur = "" : inQ = False : i = 1
  105. Do While i <= Len(line)
  106. ch = Mid(line, i, 1)
  107. If inQ Then
  108. If ch = """" Then
  109. If Mid(line, i + 1, 1) = """" Then
  110. cur = cur & """"
  111. i = i + 1
  112. Else
  113. inQ = False
  114. End If
  115. Else
  116. cur = cur & ch
  117. End If
  118. ElseIf ch = """" Then
  119. inQ = True
  120. ElseIf ch = delim Then
  121. fields(n) = cur : n = n + 1 : cur = ""
  122. Else
  123. cur = cur & ch
  124. End If
  125. i = i + 1
  126. Loop
  127. fields(n) = cur
  128. ReDim Preserve fields(n)
  129. ImportFile_SplitCsvLine = fields
  130. End Function
  131. '---------------------------------------------------------------------------------------------------------------------
  132. ' Excel (via ACE OLEDB; 32-bit provider, so this only works in a 32-bit app pool / IIS Express x86)
  133. '---------------------------------------------------------------------------------------------------------------------
  134. Function ImportFile_ReadExcel(path, ext, maxRows)
  135. Dim conn, rs, schema, sheet, props, i, n, all, rec, v, ncols
  136. If ext = "xls" Then props = "Excel 8.0" Else props = "Excel 12.0 Xml"
  137. Set conn = Server.CreateObject("ADODB.Connection")
  138. conn.Open "Provider=Microsoft.ACE.OLEDB.16.0;Data Source=" & path & ";Extended Properties=""" & props & ";HDR=YES;IMEX=1"";"
  139. Set schema = conn.OpenSchema(20) ' adSchemaTables
  140. sheet = ""
  141. Do While Not schema.EOF
  142. If schema("TABLE_TYPE") = "TABLE" Or schema("TABLE_TYPE") = "SYSTEM TABLE" Then
  143. If InStr(schema("TABLE_NAME"), "_xlnm") = 0 And InStr(schema("TABLE_NAME"), "FilterDatabase") = 0 Then
  144. sheet = schema("TABLE_NAME")
  145. Exit Do
  146. End If
  147. End If
  148. schema.MoveNext
  149. Loop
  150. schema.Close
  151. Set all = CreateObject("Scripting.Dictionary")
  152. If Len(sheet) > 0 Then
  153. Set rs = Server.CreateObject("ADODB.Recordset")
  154. rs.Open "SELECT * FROM [" & sheet & "]", conn, 0, 1
  155. ncols = rs.Fields.Count
  156. ReDim rec(ncols - 1)
  157. For i = 0 To ncols - 1
  158. rec(i) = rs.Fields(i).Name
  159. Next
  160. all.Add 0, rec
  161. Do While Not rs.EOF
  162. ReDim rec(ncols - 1)
  163. For i = 0 To ncols - 1
  164. v = rs.Fields(i).Value
  165. If IsNull(v) Then rec(i) = "" Else rec(i) = Trim(CStr(v))
  166. Next
  167. all.Add all.Count, rec
  168. If maxRows > 0 And all.Count > maxRows Then Exit Do
  169. rs.MoveNext
  170. Loop
  171. rs.Close
  172. End If
  173. conn.Close
  174. Set ImportFile_ReadExcel = ImportFile_Pack(all)
  175. End Function
  176. ' Splits the raw row dictionary (row 0 = header) into headers + data rows.
  177. Function ImportFile_Pack(all)
  178. Dim result, rows, i
  179. Set result = CreateObject("Scripting.Dictionary")
  180. Set rows = CreateObject("Scripting.Dictionary")
  181. If all.Count = 0 Then
  182. result.Add "headers", Array()
  183. Else
  184. Dim hdr : hdr = all(0)
  185. For i = 0 To UBound(hdr)
  186. hdr(i) = Trim(Replace(hdr(i), ChrW(65279), ""))
  187. Next
  188. result.Add "headers", hdr
  189. For i = 1 To all.Count - 1
  190. rows.Add rows.Count, all(i)
  191. Next
  192. End If
  193. result.Add "rows", rows
  194. Set ImportFile_Pack = result
  195. End Function
  196. Function ImportFile_Cell(rec, idx)
  197. ImportFile_Cell = ""
  198. If idx >= 0 Then
  199. If idx <= UBound(rec) Then ImportFile_Cell = Trim(rec(idx))
  200. End If
  201. End Function
  202. '=======================================================================================================================
  203. ' FIELD DEFINITIONS AND NORMALIZATION
  204. '=======================================================================================================================
  205. ' Importable fields: Array(key, label)
  206. Function ImportFile_Fields()
  207. ImportFile_Fields = Array( _
  208. Array("name", "Business name"), _
  209. Array("contact_name", "Contact name"), _
  210. Array("industry", "Industry / type of business"), _
  211. Array("phone", "Phone"), _
  212. Array("email", "Email"), _
  213. Array("website", "Website"), _
  214. Array("address1", "Address"), _
  215. Array("city", "City"), _
  216. Array("state", "State"), _
  217. Array("zip", "Zip"), _
  218. Array("notes", "Notes") _
  219. )
  220. End Function
  221. ' Guesses which field a column header represents ("" = ignore).
  222. Function ImportFile_GuessField(header)
  223. Dim h : h = LCase(Trim(header))
  224. Dim rules, r
  225. rules = Array( _
  226. Array("contact_name", "contact|owner|person|first.?name|full.?name"), _
  227. Array("email", "e-?mail"), _
  228. Array("phone", "phone|tel|mobile|cell"), _
  229. Array("website", "web|url|site"), _
  230. Array("industry", "industry|category|categories|business.?type|type|niche|sic|naics"), _
  231. Array("zip", "zip|postal|post.?code"), _
  232. Array("state", "^st$|state|province|region"), _
  233. Array("city", "city|town"), _
  234. Array("address1", "address|street"), _
  235. Array("notes", "note|comment|description"), _
  236. Array("name", "business|company|org|^name$|name") _
  237. )
  238. Dim re : Set re = New RegExp
  239. re.IgnoreCase = True
  240. For Each r In rules
  241. re.Pattern = r(1)
  242. If re.Test(h) Then
  243. ImportFile_GuessField = r(0)
  244. Exit Function
  245. End If
  246. Next
  247. ImportFile_GuessField = ""
  248. End Function
  249. ' Phone as digits only (leading US country code dropped); "" when fewer than 7 digits.
  250. Function ImportFile_PhoneDigits(phone)
  251. Dim re, d
  252. Set re = New RegExp
  253. re.Global = True
  254. re.Pattern = "[^0-9]"
  255. d = re.Replace(phone, "")
  256. If Len(d) = 11 And Left(d, 1) = "1" Then d = Mid(d, 2)
  257. If Len(d) < 7 Then d = ""
  258. ImportFile_PhoneDigits = Left(d, 20)
  259. End Function
  260. ' Digits of a search term, without the 7-digit minimum used for stored phone numbers.
  261. Function ImportFile_PhoneDigitsLoose(s)
  262. Dim re : Set re = New RegExp
  263. re.Global = True
  264. re.Pattern = "[^0-9]"
  265. ImportFile_PhoneDigitsLoose = re.Replace(s, "")
  266. End Function
  267. ' Zip codes that lost their leading zero in Excel (4 digits) get it back.
  268. Function ImportFile_NormalizeZip(zip)
  269. Dim z : z = Trim(zip)
  270. If Len(z) > 2 Then
  271. If Right(z, 2) = ".0" Then
  272. If IsNumeric(Left(z, Len(z) - 2)) Then z = Left(z, Len(z) - 2)
  273. End If
  274. End If
  275. If Len(z) = 4 And IsNumeric(z) Then z = "0" & z
  276. ImportFile_NormalizeZip = z
  277. End Function
  278. %>

Powered by TurnKey Linux.