MapBasic Workshop Peter Horsbøll Møller Systems Engineer Pitney Bowes Business Insight
Har du: Installeret MapBasic? Installeret MapInfo Pro? Medbragt filerne jeg sendte i fredags?
Målet er at lave denne dialogboks
Grundlæggende opbygning af programmer Sub Main Procedurer og funktioner Menuer Declare Dim Define MapBasic.def Forgrening: If End If
Vise værdier til brugeren Man kan nemt vise brugeren nogle værdier Dette er meget anvendeligt f.eks. til at kontrollere om programmet virker, som det skal Note kommandoen viser en dialogboks på skærmen, som brugeren skal trykke OK på for at programmet fortsætter Note Tabellen er ikke åben! Print kommandoen skriver en tekst i Meddelelsesvinduet uden at programmet stopper. Print Anvender nu den valgte tabel
Sub Main Det er denne procedure, som kaldes når MapBasic-programmet startes Her vil man ofte initiere programmet og f.eks. oprette menuer og læse opsætningsfiler Sub Main skal erklæres med Declare øverst i koden Declare Sub Main Sub Main Note Nu kører programmet! End Sub
Procedurer og funktioner Procedurer indeholder kode, som kan kaldes fra andre steder i programmet. Man kan med fordel gruppere sin kode i mindre bidder, så er den nemmere at overskue og nemmere at genbruge Funktioner er procedurer der kan returnere en værdi. Procedurer returnerer ikke direkte en værdi, men kan returnere værdier via parametrene Procedure og funktioner skal erklæres for at kunne blive anvendt. Man erklærer dem enten øverst i filen eller i en separat definitionsfil Declare Function GetPI() As Float Function GetPI() As Float GetPI = 3.14 End Function
Menuer Menuer anvendes ofte for at lade brugeren bestemme hvornår han ønsker at specifikke anvende dele af MapBasic-programmet Menuer skabes ofte i Sub Main eller i en procedure kaldt fra Sub Main Ved et klik på et menupunkt, kaldes den procedure, der er tilknyttet menupunktet Du adskiller menuer med komma (,) Hjælpeteksten, der er frivillig, vises i nederste venstre hjørne Sub Main Create Menu Mit program As Udfør handling HelpMsg Når du trykker på menuen udføres handlingen Calling DoSomething, Afslut program Calling EndProgram End Sub
Declare, Dim, Define Declare anvendes til at erklære procedurer og funktioner. Anvendes udenfor procedurer/funktioner Define anvendes til at definere konstante værdier. Anvendes udenfor procedurer/funktioner Dim anvendes til at dimensionere variable, som kan tildeles nye værdier i programmets levetid. Kan anvendes både udenfor og indeni procedurer/funktioner afhængig af hvor de skal anvendes. Declare Sub Main Define FILE_INI C:\Temp\Config.ini Dim i As Integer
Dim - datatyper Dim var_name [, var_name...] As var_type [, var_name [, var_name...] As var_type...] Dim stab, skolonne As String, nantal As Integer SmallInt Whole numbers from -32768 to 32767 (inclusive); stored in 2 bytes. Integer Whole numbers from -2,147,483,648 to +2,147,483,647 (inclusive); stored in 4 bytes. Float Floating point value; stored in eight-byte IEEE format. String Variable-length character string, up to 32768 bytes long. String * length Fixed-length character string (where length dictates the length of the string, in bytes, up to 32768 bytes); fixed-length strings are padded with trailing blanks. Logical TRUE or FALSE, stored in 1 byte: zero=false, non-zero=true. Date Date, stored in four bytes: two bytes for the year, one byte for the month, one byte for the day. DateTime DateTime is stored in nine bytes: 4 bytes for date, 5 bytes for time. 5 bytes for time include: 2 for millisec, 1 for sec, 1 for min, 1 for hour. Object Graphical object (Point, Region, Line, Polyline, Arc, Rectangle, Rounded Rectangle, Ellipse, Text, or Frame). Alias Column name. Pen Pen (line) style setting. Brush Brush (fill) style setting. Font Font (text) style setting. Symbol Symbol (point-marker) style setting.
MapBasic.def Man bør altid inkludere MapBasic.def i sit MapBasic-program. MapBasic.def indeholder en lang række konstanter, som man kan anvende i stedet for uigenkendelige numre. F.eks. konstanter for attributter til alle MapBasic funktioner, så som TableInfo(), ColumnInfo() m.fl. Øverst i dit MapBasic-program skriver du følgende for at inkludere filen: Include MapBasic.def Over tid vil du måske få brug for at inkludere flere og flere filer i dit program, andre relevante filer kunne være Menu.def og Icons.def. Derudover kan man lave sine egne filer
Forgrening: If Forgrening bruges til at styre hvilken retning programmet skal køre, afhængig af en eller flere betingelser. Man kan f.eks. bruge dette til at undersøge om der er tabeller åbne, hvis ikke bede brugeren starte med at åbne en eller flere tabeller If NumTables() = 0 Then Note Åbn først en eller flere tabeller! Exit Sub End If Kan også indeholde flere muligheder/forgreninger: If NumTables() = 0 Then Note Åbn først en eller flere tabeller! Exit Sub ElseIf NumTables() = 1 Then Note Der er kun én tabel åben! Else Note Der er & NumTables() & tabeller åbne! End If
MapBasic dialogbokse Dialog kommando Kontroller/elementer på dialogboksen Handlere til dialogbokse/kontroller Læse fra en kontrol
Dialog og Control kommandoer Dialog kommandoen starter opbygningen af en dialogboks. Dialog kommandoen efterfølgende altid af en eller flere kommandoer for Kontroller/elementer (Control) Såvel Dialog som Control kan tage en position. For Dialog er det ift. øverste venstre hjørne af skærmen. For Control er det ift. øverste venstre hjørne af dialogboksen Dialog Title Min dialogboks Control StaticText Position 5,5 Title Min tekst Control ListBox Position 5,15 Width 100 Height 100 Control OKButton
Handler Mange af kontrollerne på en MapBasic dialogboks kan have tilknyttet en handler En handler er en procedure, som kaldes når brugeren gør noget med kontrollen. Det er meget anvendelig, når man ønsker at lave en dynamisk dialogboks, som reagerer på brugerens valg, f.eks. skal listen med kolonner opdateres når brugeren vælger en anden tabel eller lignende. Dialog Title Min dialogboks Control StaticText Position 5,5 Title Min tekst Control ListBox Position 5,15 Width 100 Height 100 ID 1 Calling Handler_Listbox1 Control OKButton
Læse fra og ændre på kontroller I handleren til en kontrol kan man læse værdier fra alle kontroller på dialogboksen. Til dette formål anvendes kontrollens ID og funktionen ReadControlValue() Sub Handler_Listbox1 Note Brugeren har valgt element & ReadControlValue(1) & i listboksen End Sub I Handleren til en kontrol, kan man også ændre på kontroller på dialogboksen vælge fra ders liste eller tildele dem nye værdier/titler Igen anvendes kontrollens ID og kommandoen Alter Control Sub Handler_Listbox1 Note Brugeren har valgt element & ReadControlValue(1) & i listboksen Alter Control 1 Value 2 End Sub
Opgaver 2 OPGAVE A: Lad denne Listbox kalde proceduren MENUDialog_TabelKlik, når brugeren vælger noget i den OPGAVE B: Tilføje en text kontrol i position 115,5 med titlen "Tableinformation" TIP: Control StaticText TIP: Brug evt. en kopi af ovenstående control OPGAVE C: Tilføj en kontrol med en liste af værdier i position 115,15, lav den 300 bred og 240 høj Tildel den ID CTRL_LST_TABELINFORMATION TIP: Control Listbox TIP: Brug evt. en kopi af ovenstående control OPGAVE D: Tilføje en text kontrol i position 430,5 med titlen "Kolonneinformation" TIP: Control StaticText TIP: Brug evt. en kopi af ovenstående control
Opgaver 2 fortsat OPGAVE E: Tilføj en kontrol med en liste af værdier i position 430,15, lav den 150 bred og 110 høj Tildel den ID CTRL_LST_KOLONNEINFORMATION TIP: Control Listbox TIP: Brug evt. en kopi af ovenstående control OPGAVE F: Vis en dialogboks med en tekst, så man kan se at denne procedure kaldes ved opstart af dialogboksen TIP: Note OPGAVE G: Vis en dialogboks med en tekst, så man kan se når brugeren klikker i listboksen med ID CTRL_LST_TABELLER TIP: Note
Spørge på tabeller Antal åbne tabeller TableInfo funktionen Tabeltyper Lister med værdier (arrays) Brugerdefinerede funktioner Forgrening: Do Case End Case
Tabeller Man kan spørge på antal åbne tabeller med funktionen NumTables() Print Antal åbne tabeller: & NumTables() Man kan spørge på detaljer om en specifik tabel med TableInfo funktionen Funktionen tager følgende parametre en tabel, enten et nummer eller et navn En attribut, hvad ønsker du at vide om tabellen? Print Tabellens navn: & TableInfo(1, TAB_INFO_NAME) Print Antal poster i tabellen: & TableInfo(1, TAB_INFO_NROWS) Print Antal kolonner i tabellen: & TableInfo(1, TAB_INFO_NCOLS)
Tabeltyper Funktionen TableInfo bruges også til at finde ud af hvilken type tabel, en given tabel er. Man skal anvende flere attributter for at undersøge tabellen type. TAB_INFO_TYPE returnerer én af følgende typer: TAB_TYPE_BASE TAB_TYPE_RESULT TAB_TYPE_VIEW TAB_TYPE_IMAGE TAB_TYPE_LINKED TAB_TYPE_WMS TAB_TYPE_WFS TAB_TYPE_FME TAB_TYPE_TILESERVER TAB_INFO_TEMP: er tabellen midlertidig? TAB_INFO_SEAMLESS: Er tabellen sømløs?
Lister med værdier - arrays En variable indeholder normalt kun =en værdi. Man kan dog definere en variabel, som kan indeholde flere værdier det kaldes et array Variablen dimenioneres i såvel enten med en tom () eller med en angiven størrelse (10): Dim arrtabelnavne() As String Man læser de enkelt elementer i arrayet via deres indeksnr: Print Table 1 er: & arrtabelnavne(1) Man kan ændre størrelsen på arrayet med ReDim kommandoen ReDim arrtabelnavne(numtables())
Brugerdefinerede funktioner Man kan definere såvel egne procedurer som egne funktioner En funktion adskiller sig fra en procedure ved at returnere en værdi det gør den meget anvendelig Funktionen skal erklæres før den kan anvendes: Declare Function GetJaNejFromLogical(ByVal bvalue As Logical) As String Derefter skal den skabes, så den gør hvad den skal: Function GetJaNejFromLogical(ByVal bvalue As Logical) As String If bvalue = true Then GetJaNejFromLogical = ja Else GetJaNejFromLogical = nej End If End Function Når man sætter funktionsnavnet lig med en værdi indeni i funktionen, er det denne værdi, funktionen vil returnere
Forgrening: Do Case En anden form for forgrening er Do Case. Den er god til at sammenligne en værdi med flere mulige værdier. Do Case TableInfo(sTab, TAB_INFO_TYPE) Case TAB_TYPE_BASE MENUTabelTypeSomTekst = "Oprindelig" Case TAB_TYPE_RESULT MENUTabelTypeSomTekst = "Forespørgsel" Case TAB_TYPE_VIEW MENUTabelTypeSomTekst = "View" Case TAB_TYPE_IMAGE MENUTabelTypeSomTekst = "Raster" Case TAB_TYPE_LINKED MENUTabelTypeSomTekst = "Sammenkædet, DBMS" Case TAB_TYPE_WMS MENUTabelTypeSomTekst = "Web Map Service, WMS" Case TAB_TYPE_WFS MENUTabelTypeSomTekst = "Web Feature Service, WFS" End Case
Opgaver 3 OPGAVE A: Lav et gennemløb over antal åbne tabeller (nantaltabeller) Brug variablen ntab til at pege på den aktuelle tabel TIP: For Next OPGAVE B: Hvordan finder man ud af hvilken tab-fil en given tabel anvender? TIP: TableInfo Erstat xxx med funktionen, der returnerer navnet på tab-filen for tabellen stab OPGAVE C: Hvordan finder man ud af hvor mange kolonner en tabel har? TIP: TableInfo Erstat xxx med funktionen, der returnerer antal kolonner i tabellen stab OPGAVE D: Hvordan finder man ud af om en tabel er kortlægningsklar (mappable)? Erstat xxx med funktionen, der returnerer om tabellen stab er kortlægningsklar TIP: TableInfo
Opgaver 3 - fortsat OPGAVE E: Hvordan finder man ud af hvor mange poster/rækker der er i en tabel? Erstat xxx med funktionen, der returnerer antal rækker/poster i tabellen stab TIP: TableInfo OPGAVE F: Hvordan tilpasser man størrelsen på et array? Erstat xxx med udtrykket, der ændrer størrelsen på arrayet marrtabelinformationer til ninformation elementer TIP: Redim
Spørge på kolonner Antal kolonner i en tabel ColumnInfo funktionen Kolonnetyper
Spørge på kolonner Man kan også spørge på antal kolonner i en tabel Print Antal kolonner: & TableInfo(1, TAB_INFO_NCOLS) Print Antal kolonner: & NumCols(1) Med ColumnInfo funktionen kan man spørge på detaljer om en given kolonne Funktionen tager følgende parametre: Tabelm, enten tabelnr eller tabelnavn Kolonne, enten kolonnenavn eller COL + kolonnenr Print Navn: & ColumnInfo(sTab, "COL" & i, COL_INFO_NAME) Print Type: & ColumnInfo(sTab, "COL" & i, COL_INFO_TYPE) Print Indekseret: & ColumnInfo(sTab, "COL" & i, COL_INFO_INDEXED)
Kolonnetyper Når man forespørger på kolonnens type med COL_INFO_TYPE, returneres én af nedenstående typer: COL_TYPE_CHAR COL_TYPE_DECIMAL COL_TYPE_INTEGER COL_TYPE_SMALLINT COL_TYPE_DATE COL_TYPE_LOGICAL COL_TYPE_GRAPHIC COL_TYPE_FLOAT COL_TYPE_TIME COL_TYPE_DATETIME Nogle af typerne kræver en nærmere undersøgelse, for f.eks. at undersøge deres bredde (tekst og decimal) og antal decimaler (decimal).
Opgaver 4 OPGAVE A: Hvilken attribut skal du angive for at få navnet på kolonnen? Indtast attributten i stedet for??? OPGAVE B: Hvilken attribut skal du angive for at få typen på kolonnen? Indtast attributten i stedet for??? OPGAVE C: Hvilken attribut skal du angive for at få bredden på en tekst-kolonne? Indtast attributten i stedet for??? OPGAVE D: Hvilken konstant vil ntype svare til hvis der er tale om en kolonne af typen Dato? Indtast konstanten i stedet for???
SQL og gennemløbe tabeller SQL og aggregationer Run Command Gennemløbe en tabel, Fetch, Do Until(), EOT
SQL Vi vil i denne eksempel bruge SQL til at lave lidt statistik på en kolonnes data. Til dette anvender vi aggregationer beregninger. Aggregationer: Count(*) tæller antal poster i en gruppering Min(kolonne) beregner den mindste værdi i en kolonne i en gruppering Max(kolonne) beregner den største værdi i en kolonne i en gruppering Select Count(*) ANTAL, Min(DATA) MIN, Max(DATA) MAX From MINTABLE Into GROUPED VALUES NoSelect
Run Command Run Command kan anvendes til at køre en streng indeholdende en MapBasic kommando. Dette kan anvendes, når man skal sammensætte sin streng når programmet kører og derfor ikke kender alle tabel- og kolonnenavne Det svarer til at køre kommandoen via MapBasic-vinduet Run Command "Select Min(" & skol & ") ""MIN"", MAX(" & skol & ") ""MAKS"" From " & stab & " Into GROUPED VALUES NoSelect" Bemærk de to anførselstegn ( ) inde i tekststrengen det oversættes til en enkelt, når kommandoen køres
Gennemløbe tabeller Når man ønsker at gennemløbe og læse poster fra en tabel, er der flere måder at gøre det. Jeg anbefaler dog at man anvender nedenstående: Fetch First From GROUPED VALUES Do Until EOT(GROUPED VALUES) Print Mindste værdien er: & GROUPED VALUES.MIN Fetch Next From GROUPED VALUES Loop Fetch First og Fetch Next anvendes til at sætte cursoren på den ønskede post Do Until EOT() Loop sørger for at man gennemløber tabellen indtil cursoren ikke længere peger på en post i tabellen Inde i gennemløbet kan man læse de nødvendige værdier og behandle dem Denne fremgangsmåde hopper automatisk over slettede poster i tabellen
Opgaver 5 OPGAVE A: Tilpas nedenstående streng, så den tæller hvor mange gange hver værdi optræder Hvilken aggregation skal du indsætte i stedet for??? Tip: Kig evt. længere nede under de numeriske kolonner OPGAVE B: Lav et gennemløb af tabellen, så de første hundrede værdier tilføjes til listen marrkolonnedatainformationer Brug ntaeller til at sikre dig at du kun indlæser 100 værdier i listen/arrayet Brug ninformation til at holde styr på hvilken plads, du skal indsætte hvilken værdi i Tip: Kig evt. længere nede under de numeriske kolonner OPGAVE C: Hvordan vil du sørge for at den logiske værdi præsenteres som Ja eller Nej i stedet for T eller F?? Hvad skal der stå i stedet for??? TIP: Se hvordan værdien for TableInfo(sTab, TAB_INFO_READONLY) præsenteres længere oppe
Opgaver 6 OPGAVE A: Flyt al håndtering af kolonnetype til funktionen MENUKolonneTypeSomTekst Funktionen er defineret og findes nederst, men du skal selv fylde indhold i funktionen Funktionerne skal kaldes her fra og returværdien skal sættes sammen med teksten i marrkolonneinformationer(i)
Spørgsmål? The Power of Insight MapInfo Professional Peter Horsbøll Møller, Systems Engineer peter.moller@pb.com