Gå till innehåll

MH_

Medlem
  • Innehållsantal

    180
  • Gick med

  • Dagar vunna

    20

Inlägg postade av MH_

  1. Private Sub Worksheet_SelectionChange(ByVal Target As Range)

    Gäller bara för det blad som makrot ligger i (det ligger inte i en modul utan i bladet). Dvs "selection change"  går bara att fånga inom ett blad (så vitt jag vet. Det finns säkert andra metoder).

    *****************************************************************

    Du kan istället testa att själv-certifiera din bok.

    https://support.microsoft.com/sv-se/office/signera-ditt-vba-makroprojekt-digitalt-956e9cc8-bbf6-4365-8bfa-98505ecd1c01

    på sidan öppnar du rubriken:

    "Använda ett självsignerat certifikat"

    för att få instruktioner för att skapa ett självsignerat certifikat i din windows version.

    När du har skapat ett certifikat öppnar du ditt VBA-projekt/editor (högerklicka på flik-namnet och välj "visa kod"):

    verktyg->digital signatur

    Självsignera med ditt nyskapade certifikat

    Nu bör Excel få betydligt snällare säkerhetsspärrar för det här dokumentet. Även om det ligger på en nätverksenhet (kräver eventuellt omstart av dokument/excel).

     

    Jag är själv tvungen att göra så på jobbet eftersom IT har någon policy som ändrar mina säkerhetsinställningar i office så fort jag startat om datorn och vi har alla arbetsdokument på någon nät- eller molntjänst (vem orkar hänga med...).

    • Like 1
  2. Den enda gången jag råkat ut för det där är om jag råkat starta excel-dokument i separata instanser. Då "pratar" inte de två programinstanserna med varandra och man kan inte skapa länkar. 

    https://support.microsoft.com/sv-se/office/öppna-en-till-arbetsbok-i-en-annan-kopia-av-excel-921fa0db-cfc5-4548-8cd5-80e6333307d8

    Vette tusan hur du får bort det. Jag antar att du har startat om excel och windows?

    Om du känner dig bekväm i registret kan du kolla om du kanske har råkat ställa om standard i Excel:

    https://learn.microsoft.com/sv-se/office/troubleshoot/excel/force-excel-to-open-new-instance

     

    Annars tror jag att du får världens tråkigaste svar, kör en officereparation:

    https://support.microsoft.com/sv-se/office/reparera-ett-office-program-7821d4b6-7c1d-4205-aa0e-a6b40c5bb88b

     

  3. Min länk gick ju inte till excel VBA utan någon gammal visual basic. Wooops!🙈

     

    Kollar du excels riktiga dokumentation här:

    OpenTextFile method (Visual Basic for Applications) | Microsoft Learn

    Så är det helt andra värden för konstanterna och parametrarna skall in i en annan ordning

        '...
        MinText = MinText & """)"
    
    	Const ForReading = 1, ForWriting = 2, ForAppending = 8
        Const TristateUseDefault = -2, TristateTrue = -1, TristateFalse = 0
        
        Dim fs As Object, f As Variant
        Set fs = CreateObject("Scripting.FileSystemObject")
        Set f = fs.OpenTextFile(Filename:="C:\temp\filldown.ahk", iomode:=ForAppending, Create:=True, Format:=TristateTrue)
        f.Write MinText
        f.Close
    End sub

    eller så här om du vill ha det kompaktare (men svårbegripligare)

    '...
    MinText = MinText & """)"
            
        Dim fs As Object, f As Variant
        Set fs = CreateObject("Scripting.FileSystemObject")
        Set f = fs.OpenTextFile("C:\temp\filldown.ahk", 8, True, -1)
        f.Write MinText
        f.Close
    End Sub

     

    • Thanks 1
  4. Här diskuterar dom olika metoder:

    https://stackoverflow.com/questions/2524703/save-text-file-utf-8-encoded-with-vba

    Där jag tycker att svaret som hänvisar till

    https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-basic-6/aa265347(v=vs.60)

    verkar lättast att köra. Dvs du skippar "Print #1" helt och lägger till någonting i stil med (ombyggt från exemplet längst ner på microsoftsidan):

        '...
        MinText = MinText & """)"
        
        Const ForReading = 1, ForWriting = 2, ForAppending = 3
        Dim fs, f
        Set fs = CreateObject("Scripting.FileSystemObject")
        Set f = fs.OpenTextFile("C:\temp\filldown.ahk", ForAppending,TristateTrue)
        f.Write MinText
        f.Close
    End SUB
    
    

    Jag har inte testat men det ser ju smidigt ut. Du får väl kör en testomgång på låtsasdata.

    • Thanks 1
  5. Då räcker det väl att ersätta/förenkla 

    Sub SearchReplace(searchFor As String, replaceWith As String, ws As Worksheet)
        With ws.PageSetup
            .LeftHeader = replace(.LeftHeader, searchFor, replaceWith)
            .CenterHeader = replace(.CenterHeader, searchFor, replaceWith)
            .RightHeader = replace(.RightHeader, searchFor, replaceWith)
            .LeftFooter = replace(.LeftFooter, searchFor, replaceWith)
            .CenterFooter = replace(.CenterFooter, searchFor, replaceWith)
            .RightFooter = replace(.RightFooter, searchFor, replaceWith)
        End With
    End Sub

     

    Med

    Sub SearchReplace(searchFor As String, replaceWith As String, ws As Worksheet)
    ws.Cells.Replace What:=searchFor, Replacement:=replaceWith, LookAt:=xlPart, _
            SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _
            ReplaceFormat:=False, FormulaVersion:=xlReplaceFormula2
    End Sub

    Där du väljer vilka argument som är nödvändiga (searchOrder borde du t.ex kunna skippa)

     

    Sen kanske men inte behöver LoopWorkbook egentligen. Men har du en kod som funkar. Dont fix it

     

    • Thanks 1
  6. Man har ju nästan förträngt hur mycket tid man la ner på att ta sig runt diverse konstiga begränsningar. Det är rätt skönt att vi har kommit till den nivån av användarvänlighet att telefon- och pad generationerna inte behöver ha någon direkt koll på datorer. Vi la ner på tok för mycket tid på att få det att funka. De använder programmen till att göra saker istället (sen kan man naturligtvis diskutera hur meningsfulla de sakerna är).

  7. Inte vad du frågar om, men en relativt billig lösning om det funkar för dig.

    Du skulle ju kunna bygga om en av de "avlånga" brytarna och kör den fast monterad på din kabel (jag förutsätter att dylika hack kallas för att "göra en Mikael" i din familj).

    eller sätta en hane/hona på din befintliga kabel

    https://www.kjell.com/se/produkter/el-verktyg/el-produkter/starkstrom/timers-klockstrombrytare

    https://www.jula.se/catalog/el-och-belysning/elinstallation/plug-in-produkter/timers-och-skymningsrelaer/digital-sakerhetstimer-006052/

    https://www.elgiganten.se/product/hem-hushall-tradgard/belysning-elprodukter/elektrisk-utrustning/eluttag/proove-capidi-sakerhetstimer-ti88/TI88

    Sökordet för kontakterna verkar i alla fall var säkerhetstimer eller Korttidstimer

    • Like 1
  8. Jag fattar inte varför du inte kan klistra in allt (eller kopiera hela bladet) och sedan köra sök/ersätt. Sök/ersätt går på formlerna i alla celler och när du ersätter
    "[Ursprungligt_Exelark.xlsx]" med ingenting så försvinner de externa referenserna överallt.

     

    Självklart kan du köra någonting i stil med:

    =SUMMA.OMF(INDIREKT("Fliken_Y!C$27");INDIREKT("Fliken_Y!$B$27");"gnu")

    Men då tappar du all autofyll

    Jag tror inte att jag riktigt har förstått vad du är ute efter. 

    • Thanks 1
  9. Tror att det absolut enklaste är att klistra in och sedan köra sök/ersätt (Ctrl+H)

    Sök: [Ursprungligt_Exelark.xlsx]
    Ersätt med: (tomt, ingenting)

     

    Om det bara är någon enstaka cell så kan du kopiera från formelfältet. Dvs kopiera formeln som text.
    Alternativt kopiera från cellen i redigeringsläge ("snabb"-kommando F2, Ctrl+A, Ctrl+C, Esc)

     

    • Like 1
  10. Ahhh. nu minns jag nästan. Eller inte.

    Måste erkänna att jag aldrig tog mig längre än till demospelen (tror det fans en mask också). Hade inte råd med dator förrän man kunde sommarjobba på fabrik.  Och på universitetskurserna var det något slag pascal(?) som användes i generella programmeringsövningar. Så Qbasic kändes måttligt lockande.

  11. Hmm. Var det DOS-basic som hade ett demospel där man kastade exploderande bananer på en gorilla?
    Man var lättroad på den tiden ...

    Och till OS2 fick man med (?köpa billigt?) något slags Lotus-office där jag la ner X timmar för att träna tal-tolken så att man skulle kunna diktera texter. Bara för att inse att man tydligen talar extremt otydlig engelska. Det var mest framtiden som var bättre förr i tiden ...

  12. Namnge listan I blad3 till "gu"  
    Och namnge listan i blad 4 till "Fo"

     

    image.png.d96fceb8f539b595743051f9206e15cf.png

     

    i Blad1, A1 så skapar du en lista på vanligt sätt  (data->dataverifiering: Lista) där du läger in Fo och Gu i listan.

    i Blad1, B1 så skapar du ett villkor på vanligt sätt  (data->dataverifiering:Lista). Men du lägger in formeln

    =INDIREKT($A$1)

    image.png.fc706fc15fb04d6433b5451b4e28280f.png

    i cellen A1 kommer att kunna välja namnet på ett namngivet område (Gu eller Fo).

    I dataverifieringen för B2 berättar Indirekt() för excel att värdet som hämtas från A1 är en adress (namngivet område).

     

    *********************

    Ähhh, testa.

    Du kan börja med att peta in

    =INDIREKT($A$1)

    i en cell och se vad som händer när du ändrar värdet i A1

     

    • Thanks 1
  13. Ingen exakt lösning. Men lite byggstenar. Antag att inköpsdatum står i cell A1:

    2016-02-14 (ett högerställt, "riktigt" datum)

    Då kan du kan använda formeln IDAG() för att få dagens datum och räkna ut diffen i en anna cell. Exempel (dagar sedan inköp):

    =IDAG()-A1

    Eftersom du använder IDAG() och länkar till ett datum så kan excel försöka visa resultatet som ett datum (1907-någonting). markera cellen och tryck Ctrl+noll (0) eller högerklicka och  välj "formatera celler", tal eller allmänt.

    Det här kan du använda för att kolla om det gått 7 år

    =OM((IDAG()-A1)>365*7;"RÖD";"")

    Istället för 365*7 så kan du använda EDATUM() som räknar månader (och tar hänsyn till skottår osv) 

    =om(IDAG()>EDATUM(A1;12*7);"RÖD";"")

    Ok. Nu ville du inte ha texten "röd" utan färgen röd

    Markera cell A1
    START->Villkorsstyrd formatering->ny regel->bestäm vilka...använda en formel

    skriv in formeln

    =IDAG()>EDATUM(A1;12*7)

    image.png.a6ddbee492b35a55a9e28a642394ee9d.png

    och tryck på knappen [Formatera..], fliken fyllning och ange den färg du vill ha

     

    När du fått den tekniska livslängden att fungera så kan du lägga till flera villkor om du vill. Gå till:

    START->Villkorsstyrd formatering->Hantera regler så kan du duplicera regeln du skapade och gå in och ändra villkor/färg.

    Du kan stapla en massa villkor. Exempel som kollar om dagens datum ligger mellan 2 år och 2år+1 månad

    =OCH(IDAG()>=EDATUM(A1;12*2);IDAG()<=EDATUM(A1;12*2+1))

    image.thumb.png.24cca24ef14ca0e78ae70055c00ff503.png

    OSV.

    Det här är lite "kinkigt" avseende vilken ordning villkoren ligger och beroende på om du kryssat i "avbryt om sant".

    Du får testa och leka dig fram.

    • Like 1
  14. **ED**

    Sidlayout->Alternativ->rubriker: skriv ut

    **/ED**

    image.png.57356535552c6415ac33f6b352236c2f.png

    ***ED2***

    Vill du bara ha radnumren utan kolumnrubrikerna så kan du a bort krysset för rubriker och lägga till den här formeln i A kolumnen istället:

    RAD()

    Om dina utskrifter är bredare än en sida så får du gå till

    Sidlayout->utskriftsformat ->skriv ut rubriker   (ja, det är förvirrande med två olika saker som heter nästan samma sak ([Alt], p, i1))

    Där väljer du fliken "blad" och "kolumner till vänster". Sen markerar du kolumn A. Då kommer den alltid att synas.

    ***/ED2***

  15. >>håller inte online kurser ;) ?

    När forumen var mer aktiva så var det precis vad ett forum var. Hängde man på ett forum blev man snabbt bättre. Ett gäng som ställde frågor och ett annat gäng som höll sig uppdaterade genom att hjälpa till och läras sig av andras svar (och de som ställde frågor "betalade igen" genom att själva hjälpa till något stans).

    Jag skulle gärna skylla på alla Svärjevänner som förstörde stämningen på forum får något årtionde sen. Men sanningen är nog att den stora, anonyma och hjälpsamma  gemenskapen som fanns i nätets barndom redan hade börjat dö när Svärjevännerna härjade som värst. Trist, men kanske väntat.

    He, he. Det finns en klassisk tråd i Eforums musiktråd eller möjligtvis Studios forum när en nisse som kallar sig "Timberman" frågar om mixer-råd och åsikter om en demo. Han blev ju rätt bra på det där så småningom (se slutet av tråden, 5 år senare)... 
    https://www.studio.se/forums/topic/34925-timberman-brain/

    • Like 1
  16. När man skriver in någonting i cellen man står i, t.ex 
    Target.Value = "EJ"

    Så är det ju en "change" som inträffar och då skall ju Change_makrot köras igen, vilket kan göra en ändring som triggar igång en förändring som startar makrot som trigga....

    Det här borde lösas med hjälp av: 
    Application.EnableEvents = False

    Men eftersom jag är paranoid pga erfarenhet (Tangenten [Break] är ett viktig instrument när du skall stoppa ett makro som löpt amok... (eller var det Ctrl+break, hmmm?))

    så vill jag gärna ha både hängsle, livrem och kontorsklister för att vara säker på att byxorna sitter kvar

    If Not Len(Target.Value) = 1 Then Exit Sub

    Avbryter om cellen är tom eller om det står något i stil med "EJ 2023-02-22" (dvs om vi hamnat i en loop).

    medan "Target.Offset(1, 0).Select" i ärlighetens namn ökar risken för en loop - Tag bort- jag hade lite otur när jag tänkte...

     

    Och när jag kollar koden igen så inser jag att "EnableEvents = False" skall ligga efter de första "exit-raderna". Annars kommer excel sluta känna av "Change" så for du ändrar en cell utanför området eller skriver något annat än p,j,e i en av cellerna

    Och Case Else behövs inte heller

    Det här blir ju ganska kompakt och trevligt:

    Private Sub Worksheet_Change(ByVal Target As Range)
    ' avbryt om ändringen skedde utanförd ditt bevaknings-område
        If Intersect(Target, Range("c4:n50")) Is Nothing Then Exit Sub
    ' avbryt om mer än en cell är vald
        If Target.Cells.Count <> 1 Then Exit Sub
    ' fortsätt bara om det är exakt ett tecken i cellen
        If Len(Target.Value) <> 1 Then Exit Sub
    
    ' du bör inte stänga av "EnableEvents" förrän här eftersom ovanstående rader inte 
    ' gör något som kan uppfattas som en Change och de sätter inte på "event" innan exit
        Application.EnableEvents = False
            Select Case LCase(Target.Value)
                Case "p"
                    Target.Value = "PB " & Date
                Case "j"
                    Target.Value = "JW " & Date
                Case "e"
                    Target.Value = "EJ " & Date
            End Select
        Application.EnableEvents = True
    End Sub

     

     

    • Thanks 1
  17. Om du bara har 3 val så kan du fånga upp "Worksheet_Change" och klistra in när du tryckt enter.

    Men då bör du vara paranoid och försöka undvika evighetsloopar på alla sätt du kommer på.

    Förenklat exempel: 

    Private Sub Worksheet_Change(ByVal Target As Range)
    
    'Stäng av excels möjlighet att upptäcka Changes (försöker undvika evighetsloopar)
    Application.EnableEvents = False
    
    ' KörAvbryter bara makrot om något annat än A1 ändrades - du kör naturligtvis din kod med Intersect istället
    If Not Target.Address = "$A$1" Then Exit Sub
    
    'Avbryter om det står mer eller mindre än ett tecken i Target (ännu ett försök att undvika evighetsloopar)
    If Not Len(Target.Value) = 1 Then Exit Sub
    
    ' Använd "Select case" för att välja vad de olika initialerna skall bli (Lcase gör om till små bokstäver så att du kan skriva både små och stora initialer)
        Select Case LCase(Target.Value)
            Case "p"
                Target.Value = "PB"
            Case "j"
                Target.Value = "JW"
            Case "e"
                Target.Value = "EJ"
            Case Else
                Application.EnableEvents = True
                Exit Sub
        End Select
    
    'Och släng på mellanslag + datum
        Target.Value = Target.Value & " " & Date
    ' flyttar fokus från cellen (inte nödvändigt, men evighetslooparna...)
    Target.Offset(1, 0).Select
    
    ' och sätt på "händelsehantering" igen så att den kan uptäcka en ändring igen
    Application.EnableEvents = True
    
    End Sub

     

    Inte riktigt vad du ville. Men det borde duga.

     

    • Like 1
  18. Missade att du hade årskolumnen som x-axel också. Då behandlas hela x-axeln som text, oavsett var krysset sitter och då får man inget min/max.

    Eftersom du har centrerat B-kolumnen går det inte att se om det är datum eller text. Men om du har riktiga datum i B-kolumnen men väljer att bara visa Månad och dag  så borde det bli som du vill om du bara använder B-kolumnen för x-axeln.

    ****************************************************

    Jag skulle gör om diagrammet och bara använda B-kolumnen. Dvs strunta i årsangivelsen i A-kolumnen.

    Den stora fördelen är att X-axeln blir en riktig datumaxel. Dvs det blir kortare avstånd mellan två mätningar som sker med en veckas mellanrum jämfört med två mätningar som sker med 2 månaders mellanrum.

    Så här blir mina (nästan) slumpdata med textaxel:

    image.png.4f7a0933ebc0e7f4f50861bdb97c249c.png

    Samma data med datumaxel

    image.png.3994556023d9ebfa4c49661465c98ba8.png

    jag tvingade in kvartalsmätningar i början bara för att det skulle vara extra tydligt att avstånden blir fel med textaxel. 

     

     

  19. Det är snarare en effekt av att aftonbladet är en Stockholmstidning än att det är en morgontidning.

    Eftersom vi i det egentliga Sverige (dvs norr om skåne) har den ologiska vanan att kalla måltiden man äter strax efter middag för lunch medan kvällsmålet kallas middag så är det ju konsekvent att kalla kvällen för middagstid.

    • Like 2
    • Haha 1
  20. Du kan ju hålla isär filnamn och sökväg tills du är färdig med kontrollen. Typ:
    ...början på makrot...
    sFilnamn = ActiveWorkbook.Name
    sFilnamn = Left(sFilnamn, InStrRev(sFilnamn, "."))
    sFilnamn = sFilnamn & "pdf"
    
    If Not Dir(sSökväg & sFilnamn) = "" Then
        svar = MsgBox("Filen finns redan. Vill du ändra namn?", vbYesNo)
            If svar = vbYes Then
                sFilnamn = InputBox("Ange nytt namn", , sFilnamn)
            End If
    End If
    
    ' Sen slår du ihop den oförändrade sökvägen med det (eventuellt) ändrade filnamnet så att du bara får en sträng i ditt fortsatta makro:
    sSökväg = sSökväg & sFilnamn

    ....Resten av ditt makro....

    • Thanks 1
  21. Du kan använda DIR (funkar som gamla doskommandot). Om du tar med filnamnet i din "Dir" så kan du se om du får ett svar eller inte

    If Not Dir(sSökväg & sFilnamn) = "" Then
         MsgBox "Filen finns redan "
    End If

    Eller, med en val-box där du kan välj att avbryta

    InputBox function (Visual Basic for Applications) | Microsoft Learn
    VBA - Dialog Box - Automate Excel

    T.ex så här (avbryter om du säger nej. Annars fortsätter makrot)

    Dim svar As Integer
    If Not Dir(sSökväg & sFilnamn) = "" Then
        svar = MsgBox("Filen finns redan. Vill du skriva över?", vbYesNo)
            If svar = vbNo Then
                Exit Sub
            End If
    End If

     

    Eller så här om du vill ge chansen att byta filnamn istället

    If Not Dir(sSökväg & sFilnamn) = "" Then
        svar = MsgBox("Filen finns redan. Vill du ändra namn?", vbYesNo)
            If svar = vbYes Then
                sFilnamn = InputBox("Ange nytt namn", , sFilnamn)
            End If
    End If

    Ja. Du måste naturligtvis fixa det som skall göras före/efter. Men du fattar principen.

     

    • Thanks 1
×
×
  • Skapa nytt...