Module:Tabular data/sandbox explained

local p = local lang = mw.getContentLanguagelocal navbar = require("Module:Navbar")

local messages =

local bgColors =

local colors =

function p._cell(args) local data = args.data or mw.ext.data.get(args[1]) local rowIdx = tonumber(args.output_row) local outputFormat = args.output_format local outputColumnNames = while args["output_column" .. #outputColumnNames + 1] do table.insert(outputColumnNames, args["output_column" .. #outputColumnNames + 1]) end local outputColumnIdxs = local numOutputColumnIdxs = 0 for i, field in ipairs(data.schema.fields) do for j, outputColumnName in ipairs(outputColumnNames) do if field.name

outputColumnName then outputColumnIdxs[outputColumnName] = i numOutputColumnIdxs = numOutputColumnIdxs + 1 end end if numOutputColumnIdxs

#outputColumnNames then break end end if numOutputColumnIdxs < #outputColumnNames then for i, outputColumnName in ipairs(outputColumnNames) do assert(outputColumnIdxs[outputColumnName], mw.ustring.format("Output column “%s” not found.", outputColumnName)) end end if rowIdx > 0 then rowIdx = (rowIdx - 1) % #data.data + 1 elseif rowIdx < 0 then rowIdx = rowIdx % #data.data + 1 else error("0 is not a valid row index.") end local record = data.data[rowIdx] if record ~= nil then if outputFormat or numOutputColumnIdxs > 1 then local values = for i, columnName in ipairs(outputColumnNames) do local columnIdx = outputColumnIdxs[columnName] table.insert(values, record[columnIdx]) end if outputFormat then return mw.ustring.format(outputFormat, unpack(values)) else return mw.text.listToText(values) end else local columnIdx = outputColumnIdxs[outputColumnNames[1]] return record[columnIdx] end endend

--- Returns the value of the cell at the given row index and column name.--- A row index of 1 refers to the first row in the table. A row index of -1--- refers to the last row in the table. It is an error to specify a row index--- of 0.--- Usage: function p.cell(frame) return p._cell(frame.args)end

function p._lookup(args)

--local data = args.data or mw.ext.data.get(args[1]) local page = mw.text.trim(args[1]) -- "UN:Total population, both sexes combined.tab" -- set page name explicitly for testing local data = args.data or mw.ext.data.get(page)

local searchValue = args.search_value local searchPattern = args.search_pattern local searchColumnName = args.search_column local searchColumnIdx for i, field in ipairs(data.schema.fields) do if field.name

searchColumnName then searchColumnIdx = i end if searchColumnIdx then break end end assert(searchColumnIdx, mw.ustring.format("Search column “%s” not found.", searchColumnName)) local occurrence = tonumber(args.occurrence) or 1 local numMatchingRecords = 0 for i = (occurrence < 0 and #data.data or 1), (occurrence < 0 and 1 or #data.data), (occurrence < 0 and -1 or 1) do local record = data.data[i] if (searchValue and record[searchColumnIdx]

searchValue) or (searchPattern and mw.ustring.match(tostring(record[searchColumnIdx]), searchPattern)) then numMatchingRecords = numMatchingRecords + 1 if numMatchingRecords

math.abs(occurrence) then local args = mw.clone(args) args.data = data args.output_row = i return p._cell(args) end end endendfunction p._lookup2(args)

--local data = args.data or mw.ext.data.get(args[1]) local page = mw.text.trim(args[1]) -- "UN:Total population, both sexes combined.tab" -- set page name explicitly for testing local data = args.data or mw.ext.data.get(page)

local searchValue = args.search_value local searchPattern = args.search_pattern local searchColumnName = args.search_column local searchValue2 = args.search_value2 local searchPattern2 = args.search_pattern2 local searchColumnName2 = args.search_column2 local searchColumnIdx for i, field in ipairs(data.schema.fields) do if field.name

searchColumnName then searchColumnIdx = i end if searchColumnIdx then break end end assert(searchColumnIdx, mw.ustring.format("Search column “%s” not found.", searchColumnName))

local searchColumnIdx2 for i, field in ipairs(data.schema.fields) do if field.name

searchColumnName2 then searchColumnIdx2 = i end if searchColumnIdx2 then break end end assert(searchColumnIdx2, mw.ustring.format("Search column “%s” not found.", searchColumnName2)) local occurrence = tonumber(args.occurrence) or 1 local numMatchingRecords = 0 for i = (occurrence < 0 and #data.data or 1), (occurrence < 0 and 1 or #data.data), (occurrence < 0 and -1 or 1) do local record = data.data[i] if (searchValue and tostring(record[searchColumnIdx])

searchValue) and (searchValue2 and tostring(record[searchColumnIdx2])

searchValue2) then -- or (searchPattern and mw.ustring.match(tostring(record[searchColumnIdx]), searchPattern)) then if (1

1) then return data.data[i][3] end -- just return single occurence numMatchingRecords = numMatchingRecords + 1 if numMatchingRecords

math.abs(occurrence) then local args = mw.clone(args) args.data = data args.output_row = i return p._cell(args) end end endend

--- Returns the value of the cell(s) in the given output column(s) of the row--- matching the search key and column.--- Reminiscent of LOOKUP macros in popular spreadsheet applications, except--- that the search key must match exactly. (On the other hand, this means the--- table does not need to be sorted.)--- Usage: function p.lookup(frame) return p._lookup(frame.args)end

--- As p.lookup except requiring match of values in two columns--- Usage: function p.lookup2(frame) --return p._lookup2(frame.args) return p.lookup2_minimal(frame.args) end-- version for testing resourcesfunction p.lookup2_minimal(args) --local page = mw.text.trim(args[1]) -- "UN:Total population, both sexes combined.tab" -- set page name explicitly for testing local data = args.data or mw.ext.data.get("UN:Total population, both sexes combined.tab")

local searchValue = args.search_value --local searchPattern = args.search_pattern --local searchColumnName = args.search_column local searchValue2 = args.search_value2 --local searchPattern2 = args.search_pattern2 --local searchColumnName2 = args.search_column2 local searchColumnIdx = 1 local searchColumnIdx2 = 2

--local occurrence = tonumber(args.occurrence) or 1 local numMatchingRecords = 0 for i = 1, #data.data, 1 do local record = data.data[i] if (searchValue and tostring(record[searchColumnIdx])

searchValue) and (searchValue2 and tostring(record[searchColumnIdx2])

searchValue2) then -- or (searchPattern and mw.ustring.match(tostring(record[searchColumnIdx]), searchPattern)) then return data.data[i][3] -- just return single occurence

end endend

function p._wikitable(args) local pageName = args[1] local data = mw.ext.data.get(pageName) local datatypes = local htmlTable = mw.html.create("table") :addClass("wikitable sortable") htmlTable :tag("caption") :wikitext(navbar.navbar) :wikitext(data.description) local headerRow = htmlTable :tag("tr") for i, field in ipairs(data.schema.fields) do headerRow :tag("th") :attr("scope", "col") :attr("data-sort-type", datatypes[j]

"text" and "string" or datatypes[j]) :wikitext(field.title) datatypes[i] = field.type end for i, record in ipairs(data.data) do local row = htmlTable:tag("tr") for j = 1, #data.schema.fields do local cell = row:tag("td") if record[j] then local formattedData = record[j] if datatypes[j]

"number" then formattedData = lang:formatNum(formattedData) cell:attr("align", "right") elseif datatypes[j]

"boolean" then cell :addClass(record[j] and "table-yes" or "table-no") :css :wikitext(record[j] and messages["true"] or messages["false"]) end cell:wikitext(formattedData) else cell :addClass("mw-tabular-value-null") :addClass("table-na") :css :wikitext(messages.null) end end end local footer = htmlTable :tag("tr") :tag("td") :addClass("sortbottom") :attr("colspan", #data.schema.fields) footer:wikitext(data.sources) footer:tag("br") local licenseText = mw.message.new("Jsonconfig-license", mw.ustring.format("[%s %s]", data.license.url, data.license.text)) footer :tag("i") :wikitext(tostring(licenseText)) return htmlTableend

--- Returns a tabular data page as a wikitext table.--- Usage: function p.wikitable(frame) return p._wikitable(frame.args)end

return p