I have this table:
| 1 | 2 | 3 | 4 | 5 | 6 |
|------------------------------------------------------------------------------------------------------
| A | B | C | D | E | F | G | H | I | J | K | L | M | N | N | O | P | Q | R | S | T | U | V | W | X | Y
|------------------------------------------------------------------------------------------------------
| n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n
| n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n
| n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n
| n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n | n
where number 1-6 (but it actualy goes futher up to 12) stands for month and where "n" stands for random number.
What do I need is to add colum at the end and in each row count data from current row and up to todays month (A, E, I, M, P, T, X,...) but based on current month, so if currentmonth is 4 (by today), then sumup "n" cols (A, E, I and M), if would be only february then sumup only cells in this single row by current month (so sumup only A and E).
simple in VbA, however I need it as excel formula.
Have no idea how do I even start
Given your data layout, if you have the latest version of Excel, with the SEQUENCE function, you can use:
=SUM(INDEX(3:3, SEQUENCE(MONTH(TODAY()),,0,1)*4+1))
If you don't have the SEQUENCE function, try:
=SUM(INDEX(3:3,N(IF(1,(ROW(INDEX($A:$A,1,1):INDEX($A:$A,MONTH(TODAY()),1))-1)*4+1))))
With the latter formula, especially, you may need to "confirm" this array-formula by holding down ctrl + shift while hitting enter. If you do this correctly, Excel will place braces {...} around the formula as observed in the formula bar
You say it's simple in VBA, but you need a formula.
When you declare a VBA function as public in your module (Public Function Calculate_Month(...) as ...), you can use that function as a formula:
=Calculate_Month(...)
You can use SUMPRODUCT function:
=SUMPRODUCT((A3:X3)*($A$1:$X$1<=MONTH(TODAY()))*($A$1:$X$1<>""))
Related
I have a music note datatype defined like so:
data Note = Ab | A | Bb | B | C | Db | D | Eb | E | F | Gb | G deriving (Eq, Ord)
How can i make it an instace of Enum so that succ G returns Ab ?
You have to define the Enum instance yourself:
instance Enum Note where
fromEnum note = case note of
Ab -> 0
A -> 1
...
toEnum n = case n `mod` 12 of
0 -> Ab
1 -> A
...
The "modulo 12" part in toEnum will cycle your notes.
i need to define an instance for the class Enum based on the datatype Int'. I just need to define the functions toEnum and fromEnum.
For example: map fromEnum [Minus One .. Plus (Succ’ One)] -> [-1,0,1,2]
data PosNat = One | Succ' PosNat
data Int' = Zero' | Plus PosNat | Minus PosNat
instance Enum Int' where
toEnum 0 = Zero'
toEnum n | n>0 = Plus (toPosNat n )
toEnum n | n<0 = undefined -- Minus (toPosNat n)
where
toPosNat :: a -> PosNat
toPosNat 1 = One
toPosNat n | n>1 = (Succ' (toPosNat (n-1)) )
toPosNat n | n<1 = (Succ' (toPosNat (n+1)) )
The problem is, i get following error:
Variable not in scope: toPosNat :: Int -> PosNat
|
62 | toEnum n | n>0 = Plus (toPosNat n )
|
Thanks for your help! :)
A where clause attaches to all of the guards of a single pattern. You've defined your function using three separate patterns, so the where clause only attaches to the last of them. To fix this, simply roll the last two patterns (which are the same, minus the guards) together:
instance Enum Int' where
toEnum 0 = Zero'
toEnum n | n>0 = Plus (toPosNat n )
| n<0 = Minus (toPosNat n)
where
toPosNat :: a -> PosNat
toPosNat 1 = One
toPosNat n | n>1 = (Succ' (toPosNat (n-1)))
| n<1 = (Succ' (toPosNat (n+1)))
I've made the same change to toPosNat because this is better style, but it has no semantic impact in this case.
You need to promote toPosNat to a top-level function, like this:
instance Enum Int' where
toEnum 0 = Zero'
toEnum n | n>0 = Plus (toPosNat n )
toEnum n | n<0 = undefined -- Minus (toPosNat n)
toPosNat :: a -> PosNat
toPosNat 1 = One
toPosNat n | n>1 = (Succ' (toPosNat (n-1)) )
toPosNat n | n<1 = (Succ' (toPosNat (n+1)) )
The where clause that you have in your code is only visible in the third case, not in the second case.
I have my own data type that states:
data Commands = MoveLeft |
MoveRight |
MoveUp |
MoveDown |
IfVertical |
IfHorizontal |
InputChar |
InputInt |
OutputChar |
OutputInt |
OutputNewline |
PushInt Int |
Add |
Sub |
Mult |
Div |
Exp |
Pop |
Dup |
Switch |
Noop |
End
deriving (Show, Eq)
and I have a function, with which I'm trying to extract the number from the PushInt with:
extractNum :: PushInt -> Int
extractNum (PushInt n) = n
But when I try to run this, I get an error stating:
Parser.hs:32:19:
Not in scope: type constructor or class `PushInt'
A data constructor of that name is in scope; did you mean -XDataKinds?
As far as I knew I was allowed to extract a field from data with this method. I'm pretty sure that this is just a really simple mistake, but any help is appreciated.
Wow, was I right about a 2 am mistake. The function
extractNum :: PushInt -> Int
extractNum (PushInt n) = n
should be
extractNum :: Commands -> Int
extractNum (PushInt n) = n
For convenient analysis of data I'd like to use a library which for the following code:
data SomeType = A [String] Int | B | C Int deriving (Eq, Ord, Show)
main = do
let theData = A ["a", "b", "c"] 9 : C 3 : B : []
putStr $ treeString theData -- `treeString` is the implied library function
would produce an output similar to the following:
- A:
| - - a
| | - b
| | - c
| - 9
- C:
| - 3
- B
Is there such a library? Or maybe a better approach to such a problem?
Data.Tree has drawTree and drawForest functions with similar formatting, so you can write a function to convert your data structure to a Tree String and then use drawTree.
import Data.Tree
data SomeType = A [String] Int | B | C Int deriving (Eq, Ord, Show)
toTree :: SomeType -> Tree String
toTree (A xs n) = Node "A" [Node "*" (map (flip Node []) xs), Node (show n) []]
toTree B = Node "B" []
toTree (C n) = Node "C" [Node (show n) []]
main = do
let theData = A ["a", "b", "c"] 9 : C 3 : B : []
putStr $ drawTree (Node "*" (map toTree theData))
Output:
*
|
+- A
| |
| +- *
| | |
| | +- a
| | |
| | +- b
| | |
| | `- c
| |
| `- 9
|
+- C
| |
| `- 3
|
`- B
Adding to hammar's answer. Here's how one can do a generic conversion to Data.Tree:
import Data.Tree
import Data.Generics
import Control.Applicative
dataTree = fix . genericTree
where
genericTree :: Data a => a -> Tree String
genericTree = dflt `extQ` string
where
string x = Node x []
dflt a = Node (showConstr (toConstr a)) (gmapQ genericTree a)
fix (Node name forest)
| name == "(:)"
, a : b : [] <- forest
= Node "*" $ (fix a) : (subForest $ fix b)
| otherwise = Node name $ fix <$> forest
But for this to work on one's data types, they must have an instance of Data, which can easily be achieved by adding a {-# LANGUAGE DeriveDataTypeable #-} pragma and making the type derive from Typeable and Data like so:
data SomeType = A [String] Int | B | C Int | D [[String]]
deriving (Typeable, Data)
Sometimes I write code like this
solveLogic :: Int -> Int -> Int
solveLogic a b =
let
x = 1
brainiac
| a >= x = 1
| a == b = 333
| otherwise = 5
in
brainiac
And every time I have urge to write this things without unneeded "brainiac" function, like this:
solveLogic :: Int -> Int -> Int
solveLogic a b =
let
x = 1
in
| a >= x = 1
| a == b = 333
| otherwise = 5
Which code is much more "Haskellish". Is there any way of doing this?
Yes, using a where clause:
solveLogic a b
| a >= x = 1
| a == b = 333
| otherwise = 5
where
x = 1
When I want guards as an expression I use this somewhat ugly hack
case () of
_ | a >= x -> 1
| a == b -> 333
| otherwise -> 5