edzigmann
Hola,
Estoy buscando la forma de mostrar números como palabras usando DAX.
Tengo una medida DAX de suma básica y quiero que la pantalla se muestre en palabras, por lo que el ejemplo sería si el total es 100, entonces me gustaría que mostrara «cien» si el total suma 10.5, entonces quiero que se muestre «once».
¿Hay alguna forma de mostrar los números de la medida de esa manera?
lbendlin
En respuesta a lbendlin
Aquí hay una versión más concisa que también se puede extender fácilmente a más tripletes de dígitos, ya que la tabla de búsqueda será la misma para cada uno de los tripletes.
Spelt2 =
var l = {("1","one","eleven","ten"),("2","two","twelve","twenty"),("3","three","thirteen","thirty"),
("4","four","fourteen","fourty"),("5","five","fifteen","fifty"),("6","six","sixteen","sixty"),
("7","seven","seventeen","seventy"),("8","eight","eighteen","eighty"),("9","nine","nineteen","ninety")}
var t = "0" & format(ParameterNumber[ParameterNumber Value],"https://community.powerbi.com/t5/DAX-Commands-and-Tips/Displaying-Numbers-in-Words/m-p/#")
var s = right(t,1)
var d = left(right(t,2),1)
var h = left(right(t,3),1)
var sd = if(d="1",concatenatex(filter(l,[Value1]=s),[Value3]),concatenatex(filter(l,[Value1]=s),[Value2]))
var dd = if(d>"1" || d & s = "10",concatenatex(filter(l,[Value1]=d),[Value4]) & " ")
var hd = if(h>"0",concatenatex(filter(l,[Value1]=h),[Value2]) & " hundred ")
return hd & dd & sd
Aquí está la versión de hasta seis dígitos:
Spelt2 =
var l = {("1","one","eleven","ten"),("2","two","twelve","twenty"),("3","three","thirteen","thirty"),
("4","four","fourteen","fourty"),("5","five","fifteen","fifty"),("6","six","sixteen","sixty"),
("7","seven","seventeen","seventy"),("8","eight","eighteen","eighty"),("9","nine","nineteen","ninety")}
var t = "0" & format(ParameterNumber[ParameterNumber Value],"https://community.powerbi.com/t5/DAX-Commands-and-Tips/Displaying-Numbers-in-Words/m-p/#")
var s = right(t,1)
var d = left(right(t,2),1)
var h = left(right(t,3),1)
var ss = if(d="1",concatenatex(filter(l,[Value1]=s),[Value3]),concatenatex(filter(l,[Value1]=s),[Value2]))
var dd = if(d>"1" || d & s = "10",concatenatex(filter(l,[Value1]=d),[Value4]) & " ")
var hd = if(h>"0",concatenatex(filter(l,[Value1]=h),[Value2]) & " hundred ")
var s2 = left(right(t,4),1)
var d2 = left(right(t,5),1)
var h2 = left(right(t,6),1)
var ss2 = if(d2="1",concatenatex(filter(l,[Value1]=s2),[Value3]),concatenatex(filter(l,[Value1]=s2),[Value2]))
var dd2 = if(d2>"1" || d2 & s2 = "10",concatenatex(filter(l,[Value1]=d2),[Value4]) & " ")
var hd2 = if(h2>"0",concatenatex(filter(l,[Value1]=h2),[Value2]) & " hundred ")
return if(ss2>"",hd2 & dd2 & ss2 & " thousand ") & hd & dd & ss
En acción:
Anónimo
@edzigmann
Esto es lo que intenté implementar usando una medida.
Actualmente, esto maneja hasta 9999.
EX =
//Currently Handles Upto 9999
//Number to be converted into words. Replace this with SELECTEDVALUE or as desired.
VAR Number = SELECTEDVALUE(T[Value])//115
VAR NumberToText = "" & Number
VAR NoOfDigits =
LEN ( NumberToText )
VAR Ones =
SELECTCOLUMNS (
GENERATESERIES ( 0, 9, 1 ),
"Ones Digit", [Value],
"Ones Digit in Words", SWITCH (
[Value],
1, "One",
2, "Two",
3, "Three",
4, "Four",
5, "Five",
6, "Six",
7, "Seven",
8, "Eight",
9, "Nine"
)
)
VAR OneTens =
SELECTCOLUMNS (
GENERATESERIES ( 1, 9, 1 ),
"One Tens Digit", [Value],
"One Tens Words", SWITCH (
[Value],
1, "Eleven",
2, "Twelve",
3, "Thirteen",
4, "Fourteen",
5, "Fifteen",
6, "Sixteen",
7, "Seventeen",
8, "Eighteen",
9, "Nineteen"
)
)
VAR Tens =
SELECTCOLUMNS (
GENERATESERIES ( 1, 9, 1 ),
"Tens Place", [Value],
"Tens Words", SWITCH (
[Value],
1, "Ten",
2, "Twenty",
3, "Thirty",
4, "Fourty",
5, "Fifty",
6, "Sixty",
7, "Seventy",
8, "Eighty",
9, "Ninety"
)
)
VAR PlaceValue =
SELECTCOLUMNS (
GENERATESERIES ( 3, 6, 1 ),
"Place", [Value],
"Place Value", SWITCH ( [Value], 3, "Hundred", 4, "Thousand")
)
VAR X =
SELECTCOLUMNS (
GENERATESERIES ( 1, NoOfDigits, 1 ),
"Index", [Value],
"Dec",
VAR N =
INT ( Number / INT ( 1 & REPT ( "0", [Value] - 1 ) ) )
RETURN
MOD ( N, 10 )
)
VAR numberMod100 = MOD(Number, 100)
VAR Y =
ADDCOLUMNS (
X,
"Text", SWITCH (
TRUE (),
[Index] = 1, SWITCH (
TRUE (),
numberMod100 > 10
&& numberMod100 < 20, MAXX ( FILTER ( OneTens, [One Tens Digit] = [Dec] ), [One Tens Words] ),
MAXX ( FILTER ( Ones, [Ones Digit] = [Dec] ), [Ones Digit in Words] )
),
[Index] = 2, SWITCH (
TRUE (),
numberMod100 > 10
&& numberMod100 < 20, "",
MAXX ( FILTER ( Tens, [Tens Place] = [Dec] ), [Tens Words] )
),
// Handles for 1-9 and beyond index 2
IF (
[Dec] = 0,
"",
// get the Word representation of current Digit
MAXX ( FILTER ( Ones, [Ones Digit] = [Dec] ), [Ones Digit in Words] )
// Concatenate the current digit with its place value.
& " " & MAXX ( FILTER ( PlaceValue, [Place] = [Index] ), [Place Value] )
)
)
)
RETURN
CONCATENATEX(Y, [Text], " ", [Index], DESC)
Esto se puede ampliar para manejar cada número natural con unas pocas líneas más de DAX.
Espero que entiendas la idea.
Espero que @lbendlin pueda ayudar en esto. No sé si hay una forma mejor que esta.
Gracias
lbendlin
En respuesta a Anónimo
Para el inglés simplificado, solo necesita resolver el último grupo de tres dígitos, en un patrón de 1-2. Cualquier otro lugar de dígitos más grande es sólo una repetición, con «mil», «millones», etc.
Al menos esa es mi teoría …
lbendlin
En respuesta a lbendlin
Aquí está mi versión de los últimos tres dígitos. «ParameterNumber[ParameterNumber value]»es la medida que desea convertir. No se devuelve nada para Zero.
Spelt =
var t = "000" & format(ParameterNumber[ParameterNumber Value],"https://community.powerbi.com/t5/DAX-Commands-and-Tips/Displaying-Numbers-in-Words/m-p/#")
var s = right(t,1)
var ss = switch(s,"1","one","2","two","3","three","4","four","5","five","6","six","7","seven","8","eight","9","nine","")
var sd = right(t,2)
var sds = switch(sd,"01","one","02","two","03","three","04","four","05","five","06","six","07","seven","08","eight","09","nine","10","ten"
,"11","eleven","12","twelve","13","thirteen","14","fourteen","15","fifteen","16","sixteen","17","seventeen"
,"18","eighteen","19","nineteen","")
var t1 = left(t,len
var d = right(t1,1)
var ds = switch(d,"2","twen","3","thir","4","four","5","fif","6","six","7","seven","8","eigh","9","nine","")
var dd = switch(d,"0","","1","",ds & "ty ")
var t2 = left(t1,len(t1)-1)
var h = right(t2,1)
var hs = switch(h,"1","one","2","two","3","three","4","four","5","five","6","six","7","seven","8","eight","9","nine","")
var hd = switch(h,"0","",hs & " hundred ")
return hd & dd & if(d<"2",sds,ss)
lbendlin
En respuesta a lbendlin
Aquí hay una versión más concisa que también se puede extender fácilmente a más tripletes de dígitos, ya que la tabla de búsqueda será la misma para cada uno de los tripletes.
Spelt2 =
var l = {("1","one","eleven","ten"),("2","two","twelve","twenty"),("3","three","thirteen","thirty"),
("4","four","fourteen","fourty"),("5","five","fifteen","fifty"),("6","six","sixteen","sixty"),
("7","seven","seventeen","seventy"),("8","eight","eighteen","eighty"),("9","nine","nineteen","ninety")}
var t = "0" & format(ParameterNumber[ParameterNumber Value],"https://community.powerbi.com/t5/DAX-Commands-and-Tips/Displaying-Numbers-in-Words/m-p/#")
var s = right(t,1)
var d = left(right(t,2),1)
var h = left(right(t,3),1)
var sd = if(d="1",concatenatex(filter(l,[Value1]=s),[Value3]),concatenatex(filter(l,[Value1]=s),[Value2]))
var dd = if(d>"1" || d & s = "10",concatenatex(filter(l,[Value1]=d),[Value4]) & " ")
var hd = if(h>"0",concatenatex(filter(l,[Value1]=h),[Value2]) & " hundred ")
return hd & dd & sd
Aquí está la versión de hasta seis dígitos:
Spelt2 =
var l = {("1","one","eleven","ten"),("2","two","twelve","twenty"),("3","three","thirteen","thirty"),
("4","four","fourteen","fourty"),("5","five","fifteen","fifty"),("6","six","sixteen","sixty"),
("7","seven","seventeen","seventy"),("8","eight","eighteen","eighty"),("9","nine","nineteen","ninety")}
var t = "0" & format(ParameterNumber[ParameterNumber Value],"https://community.powerbi.com/t5/DAX-Commands-and-Tips/Displaying-Numbers-in-Words/m-p/#")
var s = right(t,1)
var d = left(right(t,2),1)
var h = left(right(t,3),1)
var ss = if(d="1",concatenatex(filter(l,[Value1]=s),[Value3]),concatenatex(filter(l,[Value1]=s),[Value2]))
var dd = if(d>"1" || d & s = "10",concatenatex(filter(l,[Value1]=d),[Value4]) & " ")
var hd = if(h>"0",concatenatex(filter(l,[Value1]=h),[Value2]) & " hundred ")
var s2 = left(right(t,4),1)
var d2 = left(right(t,5),1)
var h2 = left(right(t,6),1)
var ss2 = if(d2="1",concatenatex(filter(l,[Value1]=s2),[Value3]),concatenatex(filter(l,[Value1]=s2),[Value2]))
var dd2 = if(d2>"1" || d2 & s2 = "10",concatenatex(filter(l,[Value1]=d2),[Value4]) & " ")
var hd2 = if(h2>"0",concatenatex(filter(l,[Value1]=h2),[Value2]) & " hundred ")
return if(ss2>"",hd2 & dd2 & ss2 & " thousand ") & hd & dd & ss
En acción:
edzigmann
En respuesta a lbendlin
Esto realmente funcionó. Me tomó un tiempo entender qué está haciendo la medida, pero en realidad me gusta, ya que también puedo usarla en otros escenarios.
Muchas gracias por la ayuda. Personalmente, me pareció un buen desafío.
lbendlin
En respuesta a lbendlin
Además de ser un buen desafío de solución, esto también saca a relucir uno de los lados más feos de DAX. A diferencia de Power Query M (que tiene la capacidad de declarar funciones incluso si no se utilizan posteriormente), DAX no admite funciones «por si acaso» o la aplicación de una medida a partes de un punto de datos.
Digamos que tienes un número de siete dígitos en tu tabla y quieres deletrearlo. Lo ideal sería convertir el número en texto, dividir el texto en grupos de tres y alimentar los tripletes a través de la medida ortográfica, recibiendo el texto completo de vuelta.
Las medidas DAX no parecen funcionar de esa manera, siempre necesitan la completo valor de un existente artículo para trabajar. Tampoco admiten llamadas recursivas (hasta donde yo sé).
No estoy seguro de si los grupos de cálculo pueden ser una posible respuesta a esto, pero lo dudo mucho. @marcorusso
Marcorusso
En respuesta a lbendlin
Puede crear un grupo de cálculo Conversiones con un elemento de cálculo ToWords:
VAR OriginalValue = SELECTEDMEASURE ()
RETURN <your code to convert OriginalValue in words>
Luego aplica esa conversión a cualquier medida usando CALCULATE:
CALCULATE (
[your existing measure],
Conversions[Name] = "ToWords"
)
No me gusta, pero debería funcionar.
La realidad es que necesitamos funciones personalizadas en DAX.
lbendlin
¿en qué idiomas y dialectos? ¿Espera «dos mil ciento cuarenta y cinco» o «veintiuno cuarenta y cinco»? etc.