我有一个MsSql数据库,它以秒为单位计算两个日期之间的时间跨度。这很好。我之后在C#中使用此列并将其写入数组。
此数组是稍后的图表输入。 到目前为止,这种方法效果很好,但我无法找到以hhh:mm:ss格式显示秒数的方法,因为时间跨度可能大于24小时。
我试过ChartArea.AxisY.LabelStyle.Format =“hhmmss”;但它根本不起作用。
有人知道我该怎么做吗?
修改 我这样添加数据:
chart2.Series.Clear();
chart2.ChartAreas.Clear();
Series BoxPlotSeries = new Series();
ChartArea ChartArea2 = new ChartArea();
ChartArea ChartArea3 = new ChartArea();
chart2.ChartAreas.Add(ChartArea2);
chart2.ChartAreas.Add(ChartArea3);
ChartArea2.Name = "Data Chart Area";
ChartArea3.Name = "BoxPlotArea";
BoxPlotSeries.Name = "BoxPlotSeries";
BoxPlotSeries.ChartType = SeriesChartType.BoxPlot;
BoxPlotSeries.ChartArea = "BoxPlotArea";
chart2.Series.Add(BoxPlotSeries);
Series Input1 = new Series();
Input1.Name = "Input1";
Input1.ChartType = SeriesChartType.Point;
Input1.ChartArea = "Data Chart Area";
chart2.Series.Add(Input1);
chart2.Series["Input1"].Points.DataBindY(InputArray);
chart2.ChartAreas["BoxPlotArea"].AxisX.CustomLabels.Add(2, 0.0, "BoxPlot1");
chart2.Series["BoxPlotSeries"]["BoxPlotSeries"] = "Input1";
chart2.Series["BoxPlotSeries"]["BoxPlotShowMedian"] = "true";
chart2.Series["BoxPlotSeries"]["BoxPlotShowUnusualValues"] = "false";
chart2.Series["BoxPlotSeries"]["PointWidth"] = "0.5";
chart2.Series["BoxPlotSeries"].IsValueShownAsLabel = false;
ChartArea2.Visible = false;
ChartArea3.BackColor = Color.FromArgb(224,224,224);
//I tried to format it this way but it didn't work
//ChartArea3.AxisY.LabelStyle.Format = "{0:HHHmmss}";
chart2.ChartAreas["BoxPlotArea"].AxisX.LabelStyle.Angle = -90;
EDIT2: 这是我填充输入数组的方法
int[] InputArray = new int[1000000];
int c = 0;
con.Open();
dr = cmd.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
int n;
if (int.TryParse(dr[0].ToString(),out n) == true)
{
InputArray[c] = Convert.ToInt32(dr[0].ToString());
c++;
}
}
}
if (c == 0) { c = 1; }
Array.Resize(ref InputArray, c - 1);
在Excel中,显示小于24的小时的格式称为“[h]:mm:ss; @”
EDIT4:
感谢@TAW,我几乎设法解决了我的问题。我对他的解决方案进行了一些调整,并想出了这个:
在图表代码块中:
之前设置值“max”。
ChartArea3.AxisY.MajorTickMark.Interval = addCustomLabels(ChartArea3, BoxPlotSeries, 60 * 60, max);
int addCustomLabels(ChartArea ca, Series series, int interval, int max)
{
int tickNo = 0;
ca.AxisY.CustomLabels.Clear();
if(max / interval > 10)
{
interval = (max / 10) - (max / 10) % (60*30);
tickNo = (max / 10) - (max / 10) % (60*30);
}
if (max / interval <= 2 )
{
interval = (max / 4) - (max / 4) % (60 * 15);
tickNo = (max / 4) - (max / 4) % (60 * 15);
}
for (int i = 0; i < max; i += interval)
{
CustomLabel cl = new CustomLabel();
cl.FromPosition = i - interval / 2;
cl.ToPosition = i + interval / 2;
cl.Text = hhh_mm_ss(i);
ca.AxisY.CustomLabels.Add(cl);
}
return tickNo;
}
我现在的问题是,即使代码在没有任何问题的情况下运行,有时也不会显示轴标记(除了0:00)。
有人和想法有什么可能是错的吗?
答案 0 :(得分:0)
如果您尝试显示超过2位小时,我认为这应该适合您
//yourTimeSpan is the TimeSpan that you already have
var hoursDouble = Math.Floor(yourTimeSpan.TotalHours);
string hours;
string minutes;
string seconds;
//check hours
if(hoursDouble < 10)
{
hours = string.Format("0{0}", hoursDouble);
}
else
{
hours = hoursDouble.ToString();
}
//check minutes
if (yourTimeSpan.Minutes < 10)
{
minutes = string.Format("0{0}", yourTimeSpan.Minutes);
}
else
{
minutes = yourTimeSpan.Minutes.ToString();
}
//check seconds
if (yourTimeSpan.Seconds < 10)
{
seconds = string.Format("0{0}", yourTimeSpan.Seconds);
}
else
{
seconds = yourTimeSpan.Seconds.ToString();
}
string formattedSpan = String.Format("{0}:{1}:{2}", hours, minutes, seconds);
更新:我认为这可以解决您用单位数字看到的问题
答案 1 :(得分:0)
更新:这个答案可能对其他读者非常有用,但它几乎错过了OP的问题。我会保留它的原样,但它无助于创建特殊格式的y轴标签..
大多数图表问题源于无效或无用的x值。以下讨论试图帮助避免或绕过它们。
数字是一个数字而您无法只是将其显示为DateTime
,或者TimeSpan
。
因此,您需要将X-Values
添加为包含可转换为DateTime
的值的double
或DateTime
。我更喜欢这个...
因此,不是直接添加秒,而是将它们添加为给定DateTime
的偏移量:
改变这样的事情
series.Points.AddXY(sec, yValues);
对此:
var dt = new DateTime(0).AddSeconds(sec);
series.Points.AddXY(dt, yValues);
现在您可以根据需要使用日期和时间格式字符串..:
chartArea.AxisX.LabelStyle.Format = "{mm:ss}";
您还可以将doubles
添加为DateTimes
实际上通过ToOADate
从 series.Points.AddXY(dt.ToOADate(), yValues);
计算:
ChartValueType.DateTime
但现在您必须设置AxisX.IntervalType
,也可能设置AxisX.Interval
和s.XValueType = ChartValueType.DateTime;
ca.AxisX.Interval = 5;
ca.AxisX.IntervalType = DateTimeIntervalType.Seconds;
ca.AxisX.LabelStyle.Format = "{mm:ss}";
,以确保图表格式正确..:
X-Values
选择适合您数据的值!
注意原始代码的问题在于doubles
内部始终 ToOADate
,但秒数不是整数值它们是分数部分;所以你需要某种计算。这是OADate double
的作用。这是一个简短的测试,显示一秒实际上相当于X-Values
:
最好将DateTimes
添加为Points.DataBindY
,以便所有进一步处理都可以依赖于类型..
更新我刚看到您最终在您的问题中添加了真实代码,并且使用了Points.DataBindXY
。这不会创造有意义的X值,我很害怕。尝试切换到 int[] seconds = new int[5] { 1, 3, 88, 123, 3333 };
double[] oaSeconds = seconds.Select(x => new DateTime(0).AddSeconds(x).ToOADate())
.ToArray();
!当然,你绑定的X值也需要遵循我上面解释的规则..!
你可以在数组上循环并转换上面显示的数字;这是一个简单的例子:
onmouseover="this.stop();" onmouseout="this.start();"
答案 2 :(得分:0)
您的任务涉及两个部分:
c#中没有合适的date-time formatting string,因此我们无法使用内置的自动标签及其格式。
不幸的是,也无法使用在自动标签上调用函数的表达式。
所以我们不能使用它们。
相反,我们必须添加CustomLabels。这不是很难,但确实需要几步。
但是让我们从一个将int
转换为我们想要的hhh:mm:ss
字符串的函数开始吧。这应该做的工作:
string hhh_mm_ss(int seconds)
{
int sec = seconds % 60;
int min = ((seconds - sec)/60) % 60;
int hhh = (seconds - sec - 60 * min) / 3600;
return hhh > 0 ? string.Format("{2}:{1:00}:{0:00}", sec, min, hhh)
: min + ":" + sec.ToString("00");
}
也许它可以被优化,但为了我们的目的,它会做。
接下来,我们需要创建CustomLabels
。它们将替换普通轴标签,我们需要在每次绑定后在数据的单独循环中添加它们。
关于他们的一个特别之处是他们的定位。我们需要给出它们的两个值,即FromPosition
和ToPosition
,它们都以轴值为单位。
普通自动标签的另一个不同之处在于,我们可以根据需要创建尽可能多的或少数的标签。
此函数尝试创建一个数字,该数字将以给定的间隔达到CustomLabels
的最大y值和空间:
void addCustomLabels(ChartArea ca, Series series, int interval)
{
// we get the maximum form the 1st y-value
int max = (int)series.Points.Select(x => x.YValues[0]).Max();
// we delete any CLs we have
ca.AxisY.CustomLabels.Clear();
// now we add new custom labels
for (int i = 0; i < max; i += interval)
{
CustomLabel cl = new CustomLabel();
cl.FromPosition = i - interval / 2;
cl.ToPosition = i + interval / 2;
cl.Text = hhh_mm_ss(i);
ca.AxisY.CustomLabels.Add(cl);
}
}
调用它的第一个参数是显而易见的;然而最后一个是棘手的:
您需要决定您希望标签的间隔时间。这取决于图表的各种细节:
我没有在函数中设置任何特殊的Font
; CustomLabels
使用与普通轴标签相同的Font
,即AxisY.LabelStyle.Font
。
对于我的截图,我准备了这样的图表:
ca.AxisX.Minimum = 0;
ca.AxisY.MajorTickMark.Interval = 60 * 60; // one tick per hour
addCustomLabels(ca, s, 60 * 30); // one label every 30 minutes
我还添加了DataPoint Labels用于测试以显示值..:
series.Points[p].Label = hhh_mm_ss((int)y) + "\n" + y;
结果如下: